diff options
| author | Xin LI <delphij@FreeBSD.org> | 2026-08-15 05:47:57 +0000 |
|---|---|---|
| committer | Xin LI <delphij@FreeBSD.org> | 2026-08-15 05:47:57 +0000 |
| commit | 156348af10cecf4a1e76f3f04f463a9d8f00d00a (patch) | |
| tree | dd61f729aa42ce7d85e4ee06a95cdbd8506dfeaf | |
| parent | 4be8b0bdecb3af7c801de33f29a6821980840811 (diff) | |
Vendor import of less v704.vendor/less/v704vendor/less
| -rw-r--r-- | Makefile.aut | 1 | ||||
| -rw-r--r-- | Makefile.in | 13 | ||||
| -rw-r--r-- | NEWS | 126 | ||||
| -rw-r--r-- | README | 8 | ||||
| -rw-r--r-- | ch.c | 10 | ||||
| -rw-r--r-- | charset.c | 25 | ||||
| -rw-r--r-- | charset.h | 2 | ||||
| -rw-r--r-- | cmd.h | 3 | ||||
| -rw-r--r-- | cmdbuf.c | 6 | ||||
| -rw-r--r-- | command.c | 186 | ||||
| -rwxr-xr-x | configure | 78 | ||||
| -rw-r--r-- | configure.ac | 23 | ||||
| -rw-r--r-- | decode.c | 334 | ||||
| -rw-r--r-- | defines.h.in | 12 | ||||
| -rw-r--r-- | edit.c | 42 | ||||
| -rw-r--r-- | filename.c | 20 | ||||
| -rw-r--r-- | forwback.c | 53 | ||||
| -rw-r--r-- | funcs.h | 41 | ||||
| -rw-r--r-- | help.c | 28 | ||||
| -rw-r--r-- | input.c | 12 | ||||
| -rw-r--r-- | jump.c | 31 | ||||
| -rwxr-xr-x | less-osc8-open.sh | 64 | ||||
| -rw-r--r-- | less.h | 44 | ||||
| -rw-r--r-- | less.hlp | 26 | ||||
| -rw-r--r-- | less.man | 1375 | ||||
| -rw-r--r-- | less.nro | 327 | ||||
| -rw-r--r-- | lessecho.man | 2 | ||||
| -rw-r--r-- | lessecho.nro | 2 | ||||
| -rw-r--r-- | lesskey.man | 3 | ||||
| -rw-r--r-- | lesskey.nro | 3 | ||||
| -rw-r--r-- | lesskey_parse.c | 2 | ||||
| -rw-r--r-- | lesstest/lt/filter1.lt | 10 | ||||
| -rw-r--r-- | lesstest/lt/search-hist.lt | 6 | ||||
| -rw-r--r-- | line.c | 62 | ||||
| -rw-r--r-- | lsystem.c | 2 | ||||
| -rw-r--r-- | main.c | 73 | ||||
| -rw-r--r-- | mark.c | 50 | ||||
| -rw-r--r-- | optfunc.c | 200 | ||||
| -rw-r--r-- | opttbl.c | 60 | ||||
| -rw-r--r-- | os.c | 45 | ||||
| -rw-r--r-- | output.c | 68 | ||||
| -rw-r--r-- | pattern.c | 8 | ||||
| -rw-r--r-- | pattern.h | 10 | ||||
| -rw-r--r-- | position.c | 82 | ||||
| -rw-r--r-- | prompt.c | 33 | ||||
| -rw-r--r-- | regexp.c | 206 | ||||
| -rw-r--r-- | regexp.h | 5 | ||||
| -rw-r--r-- | screen.c | 105 | ||||
| -rw-r--r-- | search.c | 138 | ||||
| -rw-r--r-- | tags.c | 8 | ||||
| -rw-r--r-- | ttyin.c | 2 | ||||
| -rw-r--r-- | version.c | 37 |
52 files changed, 2686 insertions, 1426 deletions
diff --git a/Makefile.aut b/Makefile.aut index 863a18903d7e..1cf0a08c84d8 100644 --- a/Makefile.aut +++ b/Makefile.aut @@ -46,6 +46,7 @@ DISTFILES = \ pckeys.h pattern.h position.h xbuf.h \ install.sh defines.h.in mkinstalldirs \ less.nro less.man lesskey.nro lesskey.man lessecho.nro lessecho.man \ + less-osc8-open.sh \ less.hlp \ mkhelp.pl \ mkhelp.py \ diff --git a/Makefile.in b/Makefile.in index b2b843ef4b19..da8011c1b3b8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -31,8 +31,9 @@ LIBS = $(LIBSAN) @LIBS@ prefix = @prefix@ exec_prefix = @exec_prefix@ -# Where the installed binary goes. +# Where the installed binaries go. bindir = @bindir@ +libexecdir = @libexecdir@ binprefix = sysconfdir = @sysconfdir@ @@ -49,7 +50,7 @@ SHELL = /bin/sh # This rule allows us to supply the necessary -D options # in addition to whatever the user asks for. .c.o: - ${CC} -I. ${CFLAGS_COMPILE_ONLY} -DBINDIR=\"${bindir}\" -DSYSDIR=\"${sysconfdir}\" ${CPPFLAGS} ${CFLAGS} $< + ${CC} -I. ${CFLAGS_COMPILE_ONLY} -DBINDIR=\"${bindir}\" -DLIBEXECDIR=\"${libexecdir}\" -DSYSDIR=\"${sysconfdir}\" ${CPPFLAGS} ${CFLAGS} $< OBJ = \ main.${O} screen.${O} brac.${O} ch.${O} charset.${O} cmdbuf.${O} \ @@ -83,7 +84,8 @@ screen.${O} ttyin.${O}: pckeys.h install: all ${srcdir}/less.nro ${srcdir}/lesskey.nro ${srcdir}/lessecho.nro installdirs ${INSTALL_PROGRAM} less$(EXEEXT) ${DESTDIR}${bindir}/${binprefix}less$(EXEEXT) ${INSTALL_PROGRAM} lesskey$(EXEEXT) ${DESTDIR}${bindir}/${binprefix}lesskey$(EXEEXT) - ${INSTALL_PROGRAM} lessecho$(EXEEXT) ${DESTDIR}${bindir}/${binprefix}lessecho$(EXEEXT) + ${INSTALL_PROGRAM} lessecho$(EXEEXT) ${DESTDIR}${libexecdir}/${binprefix}lessecho$(EXEEXT) + ${INSTALL} ${srcdir}/less-osc8-open.sh ${DESTDIR}${libexecdir}/${binprefix}less-osc8-open ${INSTALL_DATA} ${srcdir}/less.nro ${DESTDIR}${mandir}/man${manext}/${manprefix}less.${manext} ${INSTALL_DATA} ${srcdir}/lesskey.nro ${DESTDIR}${mandir}/man${manext}/${manprefix}lesskey.${manext} ${INSTALL_DATA} ${srcdir}/lessecho.nro ${DESTDIR}${mandir}/man${manext}/${manprefix}lessecho.${manext} @@ -92,12 +94,13 @@ install-strip: ${MAKE} INSTALL_PROGRAM='${INSTALL_PROGRAM} -s' install installdirs: mkinstalldirs - ${srcdir}/mkinstalldirs ${DESTDIR}${bindir} ${DESTDIR}${mandir}/man${manext} + ${srcdir}/mkinstalldirs ${DESTDIR}${bindir} ${DESTDIR}${libexecdir} ${DESTDIR}${mandir}/man${manext} uninstall: rm -f ${DESTDIR}${bindir}/${binprefix}less$(EXEEXT) rm -f ${DESTDIR}${bindir}/${binprefix}lesskey$(EXEEXT) - rm -f ${DESTDIR}${bindir}/${binprefix}lessecho$(EXEEXT) + rm -f ${DESTDIR}${libexecdir}/${binprefix}lessecho$(EXEEXT) + rm -f ${DESTDIR}${libexecdir}/${binprefix}less-osc8-open rm -f ${DESTDIR}${mandir}/man${manext}/${manprefix}less.${manext} rm -f ${DESTDIR}${mandir}/man${manext}/${manprefix}lesskey.${manext} rm -f ${DESTDIR}${mandir}/man${manext}/${manprefix}lessecho.${manext} @@ -11,6 +11,132 @@ ====================================================================== + Major changes between "less" versions 702 and 704 + +* Fix possibly passing unsafe options to man when opening an + OSC 8 link (github #779). + +* Fix possibly sending unsafe OSC sequence to terminal when file + contains an unterminated OSC sequence (github #781). + +* In Examine and Shell commands, expand % and # to shell-escaped + filenames (github #784). + +====================================================================== + + Major changes between "less" versions 692 and 702 + +* Add --hilite-target option and -DJ to color target line (github #745). + +* Add --past-eof option. + +* Add --end-prompt option. + +* Add --emouse and --rmouse options, and horizontal mouse scrolling + and dragging (github #744). + +* Add -DT option to format tilde lines (github #725). + +* Change OSC 8 link handling: replace LESS_OSC8_xxx with LESS_OSC8_OPEN_xxx. + Remove %O from prompt expansion as no longer needed. + Any use of environment variables LESS_OSC8_xxx need to be manually + changed to use LESS_OSC8_OPEN_xxx. + +* Add ?o to prompt strings, to detect whether an OSC 8 link is selected. + +* When scrolling past end-of-file or before beginning-of-file, + stop when exactly one line is left on screen. + +* Make -w/-W highlight lines when moving backward as well as forward + (github #729). + +* Display pattern in "Pattern not found" message (github #731). + +* Allow m and M commands to take a numeric argument to specify the + line to be marked (github #736). + +* Allow ' command to take a numeric argument to specify the screen + position on which to place the marked line. + +* Allow lesskey to map keypad ENTER with \kpe (github #761). + +* Add "noaction" as a possible action in #line-edit section + in a lesskey file (github #761). + +* Support POSIX character classes with the built-in V8 regex library + (github #732). + +* Change | command to pipe just one line if the marked line is at the + top of the screen (github #733). + +* If OSC8 handler command begins with "-", suppress command echo, + and if it begins with ctrl-P, suppress "done" message (github #747). + +* Don't ask for confirmation when input is a binary file and stdout is + redirected. Fixes infinite loop in that situation (github #719). + +* Make early error messages go to stderr if stdout is redirected + (github #719). + +* Don't retry read after read error; fixes hang when attempting to read + a directory or other unreadable file (github #741). + +* Fix incorrect restoration of saved mark if not at top of screen. + +* With --save-marks, don't save a mark that was cleared with ESC-m. + +* Fix buffer overflow when using malformed lesskey file (github #721). + +* Fix unexpected scrolling past end of file (github #720). + +* Fix bug when env var in LESSKEY_CONTENT partially matches env var + defined in lesskey file (github #727). + +* Fix bug when env var in lesskey file matches tail of env var used + by less (github #728). + +* Fix command parsing bug when one command is a substring of another. + Also fixes --no-paste option (github #724). + +* Fix incorrect display using --color to set character attributes + without color, such as -DS-u (github #730). + +* Fix crash when tags file contains invalid line number 0 (github #743). + +* Fix build when tparm() doesn't use varargs (github #748). + +* Fix prompt overflow when filtering with long prompt (github #749). + +* Fix incorrect highlighting when change -i while filtering (github #750). + +* Fix erroneous error mesage using --show-preproc-error with + some shells (github #753). + +* Fix erroneous highlighting when using a search pattern containing more + than 5 pairs of parentheses with PCRE2 (github #754). + +* When ^X interrupts F mode, discard pending keys as is done when + ^C interrupts it (github #757). + +* Fix bug in Windows where pressing any key during "waiting for data" would + prevent a subsequent ^X from working. + +* Fix erroneous display in some situations when using LESS_LINES (github #759). + +* Fix erroneous display after certain messages are displayed in a + very narrow terminal (github #760). + +* Don't init terminal if stdout is not a tty (github #768). + +* Fix bug clicking OSC 8 link that crosses a screen line boundary + (github #775). + +* Fix beeps when resizing window on Windows (github #771). + +* Fix beeps when paging continuously on Windows (github #772). + +====================================================================== + Major changes between "less" versions 691 and 692 * Revert HOME key to scroll to beginning of file and END key @@ -100,14 +100,6 @@ INSTALLATION (Unix & Linux systems only): bindir and/or mandir to the appropriate directories. -Note to hackers: comments noting possible improvements are enclosed -in double curly brackets {{ like this }}. - -(Note that the above note was originally written at a time when -"hackers" most commonly meant "enthusiastic and dedicated computer -programmers", not "persons who attempt to circumvent computer security".) - - ======================================================================= INSTALLATION (Windows-95, Windows-98 and Windows-NT systems only, @@ -23,6 +23,7 @@ typedef POSITION BLOCKNUM; public lbool ignore_eoi = FALSE; +public lbool read_error = FALSE; /* * Pool of buffers holding the most recently used blocks of the input file. @@ -292,13 +293,14 @@ static int ch_get(void) if (n < 0) { #if MSDOS_COMPILER==WIN32C - if (errno != EPIPE) + if (errno == EPIPE) + n = 0; + else #endif { - error("read error", NULL_PARG); - clear_eol(); + read_error = TRUE; + return (EOI); } - n = 0; } #if LOGFILE diff --git a/charset.c b/charset.c index 74159404148b..f2020e4ef5c5 100644 --- a/charset.c +++ b/charset.c @@ -585,20 +585,21 @@ public constant char * prutfchar(LWCHAR ch) /* * Get the length of a UTF-8 character in bytes. */ -public int utf_len(char ch) +public int utf_len(char ach) { - if ((ch & 0x80) == 0) + unsigned char ch = (unsigned char) ach; + if (IS_ASCII_OCTET(ch)) return 1; - if ((ch & 0xE0) == 0xC0) + if (IS_UTF8_LEAD2(ch)) return 2; - if ((ch & 0xF0) == 0xE0) + if (IS_UTF8_LEAD3(ch)) return 3; - if ((ch & 0xF8) == 0xF0) + if (IS_UTF8_LEAD4(ch)) return 4; #if 0 - if ((ch & 0xFC) == 0xF8) + if (IS_UTF8_LEAD5(ch)) return 5; - if ((ch & 0xFE) == 0xFC) + if (IS_UTF8_LEAD6(ch)) return 6; #endif /* Invalid UTF-8 encoding. */ @@ -608,16 +609,17 @@ public int utf_len(char ch) /* * Does the parameter point to the lead byte of a well-formed UTF-8 character? */ -public lbool is_utf8_well_formed(constant char *ss, int slen) +public lbool is_utf8_well_formed(constant char *ssa, int slen) { int i; int len; - unsigned char s0 = (unsigned char) ss[0]; + constant unsigned char *ss = (constant unsigned char *) ssa; + unsigned char s0 = ss[0]; - if (IS_UTF8_INVALID(s0)) + if (IS_UTF8_LEAD5(s0) || IS_UTF8_LEAD6(s0) || IS_UTF8_INVALID(s0)) return (FALSE); - len = utf_len(ss[0]); + len = utf_len(s0); if (len > slen) return (FALSE); if (len == 1) @@ -904,6 +906,7 @@ public lbool is_composing_char(LWCHAR ch) public lbool is_ubin_char(LWCHAR ch) { if (is_in_table(ch, &user_prt_table)) return FALSE; + if (ch > MAX_UNICODE) return TRUE; return is_in_table(ch, &user_ubin_table) || (is_in_table(ch, &ubin_table) || (bs_mode == BS_CONTROL && is_in_table(ch, &fmt_table) && diff --git a/charset.h b/charset.h index cf2e02547cb5..dab7474acc73 100644 --- a/charset.h +++ b/charset.h @@ -16,3 +16,5 @@ #define IS_UTF8_LEAD6(c) (((c) & 0xFE) == 0xFC) #define IS_UTF8_INVALID(c) (((c) & 0xFE) == 0xFE) #define IS_UTF8_LEAD(c) (((c) & 0xC0) == 0xC0 && !IS_UTF8_INVALID(c)) + +#define MAX_UNICODE 0x10FFFF @@ -87,6 +87,8 @@ #define A_START_PASTE 75 /* must not overlap EC_* */ #define A_END_PASTE 76 /* must not overlap EC_* */ #define A_F_FOREVER_BELL 77 +#define A_L_MOUSE 78 +#define A_R_MOUSE 79 /* These values must not conflict with any A_* or EC_* value. */ #define A_INVALID 100 @@ -178,5 +180,6 @@ #define SK_CTL_END 37 #define SK_SHIFT_LEFT_ARROW 38 #define SK_SHIFT_RIGHT_ARROW 39 +#define SK_PAD_ENTER 41 #define SK_CONTROL_K 40 @@ -113,8 +113,8 @@ static struct mlist *curr_mlist = NULL; static int curr_cmdflags; static char cmd_mbc_buf[MAX_UTF_CHAR_LEN]; -static int cmd_mbc_buf_len; -static int cmd_mbc_buf_index; +static size_t cmd_mbc_buf_len; +static size_t cmd_mbc_buf_index; /* @@ -1330,7 +1330,7 @@ static int cmd_uchar(char c, size_t *plen) goto retry; } - *plen = (size_t) cmd_mbc_buf_len; /*{{type-issue}}*/ + *plen = cmd_mbc_buf_len; cmd_mbc_buf_len = 0; } return (CC_PASS); diff --git a/command.c b/command.c index fcb6ec13569b..0fc2b7ae21fa 100644 --- a/command.c +++ b/command.c @@ -23,10 +23,11 @@ extern int erase_char, erase2_char, kill_char; extern int sigs; extern int quit_if_one_screen; -extern int one_screen; +extern lbool one_screen; extern int sc_width; extern int sc_height; extern char *kent; +extern lbool kent_mapped; extern int swindow; extern int jump_sline; extern lbool quitting; @@ -47,13 +48,16 @@ extern void *ml_search; extern void *ml_examine; extern int wheel_lines; extern int def_search_type; +extern int hilite_target; extern lbool search_wrapped; extern int no_paste; extern lbool pasting; extern int no_edit_warn; +extern lbool read_error; extern POSITION soft_eof; extern POSITION search_incr_start; extern char *first_cmd_at_prompt; +extern lbool prompting; #if SHELL_ESCAPE || PIPEC extern void *ml_shell; #endif @@ -64,9 +68,9 @@ extern constant char *editproto; extern char *osc8_uri; #endif extern int shift_count; -extern int forw_prompt; +extern lbool forw_prompt; extern int incr_search; -extern int full_screen; +extern lbool full_screen; #if MSDOS_COMPILER==WIN32C extern int utf_mode; extern unsigned less_acp; @@ -84,6 +88,7 @@ static struct loption *curropt; static lbool opt_lower; static int optflag; static lbool optgetname; +static POSITION toppos; static POSITION bottompos; static int save_hshift; static int save_bs_mode; @@ -207,7 +212,7 @@ static void mca_search1(void) cmd_putstr("/"); else cmd_putstr("?"); - forw_prompt = 0; + forw_prompt = FALSE; } static void mca_search(void) @@ -247,7 +252,7 @@ static void mca_opt_toggle(void) cmd_putstr("!"); break; } - forw_prompt = 0; + forw_prompt = FALSE; set_mlist(NULL, CF_OPTION); } @@ -846,12 +851,6 @@ public int is_screen_trashed(void) static void make_display(void) { /* - * If not full_screen, we can't rely on scrolling to fill the screen. - * We need to clear and repaint screen before any change. - */ - if (!full_screen && !(quit_if_one_screen && one_screen)) - lclear(); - /* * If nothing is displayed yet, display starting from initial_scrpos. */ if (empty_screen()) @@ -880,11 +879,46 @@ static void make_display(void) } /* + * Display any message that needs to be displayed before the prompt. + */ +static void prompt_message(void) +{ + if (read_error) + { + error("read error", NULL_PARG); + read_error = FALSE; + } + if (search_wrapped) + { + if (search_type & SRCH_BACK) + error("Search hit top; continuing at bottom", NULL_PARG); + else + error("Search hit bottom; continuing at top", NULL_PARG); + search_wrapped = FALSE; + } +#if OSC8_LINK + if (osc8_uri != NULL) + { + PARG parg; + parg.p_string = osc8_uri; + error("Link: %s", &parg); + free(osc8_uri); + osc8_uri = NULL; + } +#endif +} + +/* * Display the appropriate prompt. */ static void prompt(void) { constant char *p; + int attr; +#if MSDOS_COMPILER==WIN32C + WCHAR w[MAX_PATH*2]; + char a[MAX_PATH*2]; +#endif if (ungot != NULL && !ungot->ug_end_command) { @@ -899,6 +933,10 @@ static void prompt(void) * Make sure the screen is displayed. */ make_display(); + + if (hilite_target) + draw_target_attn(TRUE); /* Redraw target line for --hilite-target. */ + toppos = position(TOP); bottompos = position(BOTTOM_PLUS_ONE); /* @@ -916,7 +954,7 @@ static void prompt(void) entire_file_displayed() && !(ch_getflags() & CH_HELPFILE) && next_ifile(curr_ifile) == NULL_IFILE) quit(QUIT_OK); - quit_if_one_screen = FALSE; /* only get one chance at this */ + quit_if_one_screen = 0; /* only get one chance at this */ if (first_cmd_at_prompt != NULL) { ungetsc(first_cmd_at_prompt); @@ -927,6 +965,7 @@ static void prompt(void) #if MSDOS_COMPILER==WIN32C /* * In Win32, display the file name in the window title. + * {{ Seems like this should be done in edit_ifile, not on every prompt. }} */ if (!(ch_getflags() & CH_HELPFILE)) { @@ -953,50 +992,43 @@ static void prompt(void) if (!forw_prompt) clear_bot(); clear_cmd(); - forw_prompt = 0; + forw_prompt = FALSE; + prompt_message(); + /* We called make_display above, but if prompt_message displayed + * a message longer than the screen width, we may have trashed + * the screen and need to call make_display again. */ + if (is_screen_trashed()) + make_display(); p = pr_string(); -#if HILITE_SEARCH - if (is_filtering()) - putstr("& "); -#endif - if (search_wrapped) - { - if (search_type & SRCH_BACK) - error("Search hit top; continuing at bottom", NULL_PARG); - else - error("Search hit bottom; continuing at top", NULL_PARG); - search_wrapped = FALSE; - } -#if OSC8_LINK - if (osc8_uri != NULL) - { - PARG parg; - parg.p_string = osc8_uri; - error("Link: %s", &parg); - free(osc8_uri); - osc8_uri = NULL; - } -#endif if (p == NULL || *p == '\0') { - at_enter(AT_NORMAL|AT_COLOR_PROMPT); - putchr(':'); - at_exit(); + p = ":"; + attr = AT_NORMAL|AT_COLOR_PROMPT; } else { + attr = AT_STANDOUT|AT_COLOR_PROMPT; #if MSDOS_COMPILER==WIN32C - WCHAR w[MAX_PATH*2]; - char a[MAX_PATH*2]; MultiByteToWideChar(less_acp, 0, p, -1, w, countof(w)); WideCharToMultiByte(utf_mode ? CP_UTF8 : GetConsoleOutputCP(), 0, w, -1, a, sizeof(a), NULL, NULL); p = a; #endif - load_line(p); - put_line(FALSE); } +#if HILITE_SEARCH + if (is_filtering()) + { + constant char *amp = "& "; + load_line(p, attr, strlen(amp)+1); + putstr(amp); + } else +#endif + { + load_line(p, attr, 1); + } + put_line(FALSE); clear_eol(); resume_screen(); + prompting = TRUE; } /* @@ -1134,8 +1166,9 @@ static char getcc_repl(char constant *orig, char constant *repl, char (*gr_getc) */ public char getcc(void) { - /* Replace kent (keypad Enter) with a newline. */ - return getcc_repl(kent, "\n", getccu, ungetcc); + /* Replace kent (keypad Enter) with a newline. + * However don't do this if kent is mapped to a command via lesskey. */ + return getcc_repl(kent_mapped ? NULL : kent, "\n", getccu, ungetcc); } /* @@ -1286,7 +1319,14 @@ static void multi_search(constant char *pattern, int n, int silent) * Print an error message if we haven't already. */ if (n > 0 && !silent) - error("Pattern not found", NULL_PARG); + { + PARG parg; + parg.p_string = prev_pattern_text(); + if (parg.p_string == NULL) /* {{ can this happen? }} */ + error("Pattern not found", NULL_PARG); + else + error("Pattern not found: %s", &parg); + } if (changed_file) { @@ -1343,7 +1383,7 @@ static int forw_loop(int action) /* * Ignore subsequent (pasted) input chars. */ -public void start_ignoring_input() +public void start_ignoring_input(void) { ignoring_input = TRUE; #if HAVE_TIME @@ -1354,7 +1394,7 @@ public void start_ignoring_input() /* * Stop ignoring input chars. */ -public void stop_ignoring_input() +public void stop_ignoring_input(void) { ignoring_input = FALSE; pasting = FALSE; @@ -1438,6 +1478,8 @@ public void commands(void) c = getcc(); again: + if (c == READ_AGAIN) + continue; if (sigs) continue; @@ -1577,12 +1619,13 @@ public void commands(void) if (number <= 0) number = get_swindow(); cmd_exec(); + if (show_attn && toppos != NULL_POSITION && toppos > ch_zero()) + set_attnpos(toppos-1); backward((int) number, FALSE, TRUE, FALSE); break; case A_F_LINE: case A_F_NEWLINE: - /* * Forward N (default 1) line. */ @@ -1602,6 +1645,8 @@ public void commands(void) if (number <= 0) number = 1; cmd_exec(); + if (show_attn == OPT_ONPLUS && number > 1 && toppos != NULL_POSITION && toppos > ch_zero()) + set_attnpos(toppos-1); backward((int) number, FALSE, FALSE, action == A_B_NEWLINE && !chopline); break; @@ -1621,6 +1666,29 @@ public void commands(void) backward(wheel_lines, FALSE, FALSE, FALSE); break; + case A_L_MOUSE: + /* + * Left wheel_lines columns. + */ + cmd_exec(); + pos_rehead(FALSE); + if (wheel_lines > hshift) + hshift = 0; + else + hshift -= wheel_lines; + screen_trashed(); + break; + + case A_R_MOUSE: + /* + * Right wheel_lines columns. + */ + cmd_exec(); + pos_rehead(FALSE); + hshift += wheel_lines; + screen_trashed(); + break; + case A_FF_LINE: /* * Force forward N (default 1) line. @@ -1640,6 +1708,8 @@ public void commands(void) if (number <= 0) number = 1; cmd_exec(); + if (show_attn == OPT_ONPLUS && number > 1 && toppos != NULL_POSITION && toppos > ch_zero()) + set_attnpos(toppos-1); backward((int) number, TRUE, FALSE, FALSE); break; @@ -1662,6 +1732,8 @@ public void commands(void) if (number <= 0) number = get_swindow(); cmd_exec(); + if (show_attn == OPT_ONPLUS && toppos != NULL_POSITION && toppos > ch_zero()) + set_attnpos(toppos-1); backward((int) number, TRUE, FALSE, FALSE); break; @@ -1699,6 +1771,8 @@ public void commands(void) if (number > 0) wscroll = (int) number; cmd_exec(); + if (show_attn == OPT_ONPLUS && toppos != NULL_POSITION && toppos > ch_zero()) + set_attnpos(toppos-1); backward(wscroll, FALSE, FALSE, FALSE); break; @@ -1958,6 +2032,7 @@ public void commands(void) /* * Clear search string highlighting. */ + cmd_exec(); undo_search(action == A_CLR_SEARCH); break; @@ -2224,9 +2299,11 @@ public void commands(void) } start_mca(A_SETMARK, "set mark: ", NULL, 0); c = getcc(); + make_display(); + cmd_exec(); if (is_erase_char(c) || is_newline_char(c)) break; - setmark(c, action == A_SETMARKBOT ? BOTTOM : TOP); + setmark(c, action == A_SETMARKBOT ? BOTTOM : TOP, number); repaint(); break; @@ -2236,6 +2313,7 @@ public void commands(void) */ start_mca(A_CLRMARK, "clear mark: ", NULL, 0); c = getcc(); + cmd_exec(); if (is_erase_char(c) || is_newline_char(c)) break; clrmark(c); @@ -2251,7 +2329,7 @@ public void commands(void) if (is_erase_char(c) || is_newline_char(c)) break; cmd_exec(); - gomark(c); + gomark(c, number); break; case A_PIPE: @@ -2294,7 +2372,7 @@ public void commands(void) number = (shift_count > 0) ? shift_count : sc_width / 2; if (number > hshift) number = hshift; - pos_rehead(); + pos_rehead(FALSE); hshift -= (int) number; screen_trashed(); cmd_exec(); @@ -2308,7 +2386,7 @@ public void commands(void) shift_count = (int) number; else number = (shift_count > 0) ? shift_count : sc_width / 2; - pos_rehead(); + pos_rehead(FALSE); hshift += (int) number; screen_trashed(); cmd_exec(); @@ -2318,7 +2396,7 @@ public void commands(void) /* * Shift view left to margin. */ - pos_rehead(); + pos_rehead(FALSE); hshift = 0; screen_trashed(); cmd_exec(); @@ -2328,7 +2406,7 @@ public void commands(void) /* * Shift view right to view rightmost char on screen. */ - pos_rehead(); + pos_rehead(FALSE); hshift = rrshift(); screen_trashed(); cmd_exec(); diff --git a/configure b/configure index fe562fa1e425..f3b736359568 100755 --- a/configure +++ b/configure @@ -3684,7 +3684,6 @@ fi - # Find a good install program. We prefer a C program (faster), # so one script is as good as another. But avoid the broken or # incompatible versions: @@ -4978,23 +4977,85 @@ cat confdefs.h - <<_ACEOF >conftest.$ac_ext int main (void) { -setupterm("",0,0); tigetflag(""); tigetnum(""); tigetstr("") +setupterm("",0,0); tigetflag(""); tigetnum(""); tigetstr(""); ; return 0; } _ACEOF if ac_fn_c_try_link "$LINENO" then : - { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 -printf "%s\n" "yes" >&6; }; printf "%s\n" "#define HAVE_TERMINFO 1" >>confdefs.h - + maybe_have_terminfo=yes else case e in #( - e) { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 -printf "%s\n" "no" >&6; } ;; + e) maybe_have_terminfo=no ;; esac fi rm -f core conftest.err conftest.$ac_objext conftest.beam \ conftest$ac_exeext conftest.$ac_ext +if test $maybe_have_terminfo = yes; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <curses.h> +#include <term.h> +int +main (void) +{ +tparm("x",0,0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + printf "%s\n" "#define HAVE_TPARM2 1" >>confdefs.h + have_terminfo=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <curses.h> +#include <term.h> +int +main (void) +{ +tparm("x",0,0,0,0,0,0,0,0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + printf "%s\n" "#define HAVE_TPARM8 1" >>confdefs.h + have_terminfo=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +#include <curses.h> +#include <term.h> +int +main (void) +{ +tparm("x",0,0,0,0,0,0,0,0,0); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO" +then : + printf "%s\n" "#define HAVE_TPARM9 1" >>confdefs.h + have_terminfo=yes +fi +rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext +fi +if test "$have_terminfo" = yes; then + printf "%s\n" "#define HAVE_TERMINFO 1" >>confdefs.h + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +printf "%s\n" "yes" >&6; } ; else { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no" >&5 +printf "%s\n" "no" >&6; } +fi fi @@ -5030,6 +5091,9 @@ fi + + + # Checks for identifiers. { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for void" >&5 printf %s "checking for void... " >&6; } diff --git a/configure.ac b/configure.ac index e56c10a35d9e..1dbe0577e708 100644 --- a/configure.ac +++ b/configure.ac @@ -16,7 +16,6 @@ AC_CONFIG_HEADERS([defines.h]) # Checks for programs. AC_PROG_CC AC_SEARCH_LIBS([strerror],[cposix]) -AC_PROG_GCC_TRADITIONAL AC_PROG_INSTALL # Checks for compilation model. @@ -192,7 +191,21 @@ LIBS="$LIBS $TERMLIBS" AC_MSG_CHECKING(for terminfo) AC_LINK_IFELSE([AC_LANG_PROGRAM([[ #include <curses.h> -#include <term.h>]], [[setupterm("",0,0); tigetflag(""); tigetnum(""); tigetstr("")]])],[AC_MSG_RESULT(yes); AC_DEFINE(HAVE_TERMINFO)],[AC_MSG_RESULT(no)]) +#include <term.h>]], [[setupterm("",0,0); tigetflag(""); tigetnum(""); tigetstr("");]])], [maybe_have_terminfo=yes], [maybe_have_terminfo=no]) +if test $maybe_have_terminfo = yes; then + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include <curses.h> +#include <term.h>]], [[tparm("x",0,0);]])], AC_DEFINE(HAVE_TPARM2) have_terminfo=yes, ) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include <curses.h> +#include <term.h>]], [[tparm("x",0,0,0,0,0,0,0,0);]])], AC_DEFINE(HAVE_TPARM8) have_terminfo=yes,) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include <curses.h> +#include <term.h>]], [[tparm("x",0,0,0,0,0,0,0,0,0);]])], AC_DEFINE(HAVE_TPARM9) have_terminfo=yes, ) +fi +if test "$have_terminfo" = yes; then + AC_DEFINE(HAVE_TERMINFO) AC_MSG_RESULT(yes) ; else AC_MSG_RESULT(no) +fi fi @@ -253,6 +266,12 @@ AH_TEMPLATE([HAVE_SIGSETJMP], [Define HAVE_SIGSETJMP if you have sigsetjmp and siglongjmp.]) AH_TEMPLATE([HAVE_TERMINFO], [Define HAVE_TERMINFO if you have the terminfo library.]) +AH_TEMPLATE([HAVE_TPARM2], + [Define HAVE_TPARM2 if your terminfo library supports tparm with 2 parameters.]) +AH_TEMPLATE([HAVE_TPARM8], + [Define HAVE_TPARM8 if your terminfo library supports tparm with 8 parameters.]) +AH_TEMPLATE([HAVE_TPARM9], + [Define HAVE_TPARM9 if your terminfo library supports tparm with 9 parameters.]) AH_TEMPLATE([EDIT_PGM], [Define EDIT_PGM to your editor.]) AH_TEMPLATE([SECURE_COMPILE], @@ -34,12 +34,12 @@ #include "lesskey.h" extern int erase_char, erase2_char, kill_char; -extern int mousecap; +extern int emouse; +extern int mouse_reverse; +extern int hshift; extern int sc_height; extern char *no_config; -static constant lbool allow_drag = TRUE; - #if USERFILE /* "content" is lesskey source, never binary. */ static void add_content_table(int (*call_lesskey)(constant char *, lbool), constant char *envname, lbool sysvar); @@ -286,17 +286,19 @@ static unsigned char edittable[] = ESC,'[','2','0','1','~',0, A_END_PASTE, /* close paste bracket */ }; -static unsigned char dflt_vartable[] = +/* + * Default environment variables. + * Note: "\201" is (A_EXTRA|EV_OK). + */ +static char dflt_vartable[] = { - 'L','E','S','S','_','O','S','C','8','_','m','a','n', 0, EV_OK|A_EXTRA, - /* echo '%o' | sed -e "s,^man\:\\([^(]*\\)( *\\([^)]*\\)\.*,-man '\\2' '\\1'," -e"t X" -e"s,\.*,-echo Invalid man link," -e"\: X" */ - 'e','c','h','o',' ','\'','%','o','\'',' ','|',' ','s','e','d',' ','-','e',' ','"','s',',','^','m','a','n','\\',':','\\','\\','(','[','^','(',']','*','\\','\\',')','(',' ','*','\\','\\','(','[','^',')',']','*','\\','\\',')','\\','.','*',',','-','m','a','n',' ','\'','\\','\\','2','\'',' ','\'','\\','\\','1','\'',',','"',' ','-','e','"','t',' ','X','"',' ','-','e','"','s',',','\\','.','*',',','-','e','c','h','o',' ','I','n','v','a','l','i','d',' ','m','a','n',' ','l','i','n','k',',','"',' ','-','e','"','\\',':',' ','X','"', - 0, - - 'L','E','S','S','_','O','S','C','8','_','f','i','l','e', 0, EV_OK|A_EXTRA, - /* eval `echo '%o' | sed -e "s,^file://\\([^/]*\\)\\(.*\\),_H=\\1;_P=\\2;_E=0," -e"t X" -e"s,.*,_E=1," -e": X"`; if [ "$_E" = 1 ]; then echo -echo Invalid file link; elif [ -z "$_H" -o "$_H" = localhost -o "$_H" = $HOSTNAME ]; then echo ":e $_P"; else echo -echo Cannot open remote file on "$_H"; fi */ - 'e','v','a','l',' ','`','e','c','h','o',' ','\'','%','o','\'',' ','|',' ','s','e','d',' ','-','e',' ','"','s',',','^','f','i','l','e','\\',':','/','/','\\','\\','(','[','^','/',']','*','\\','\\',')','\\','\\','(','\\','.','*','\\','\\',')',',','_','H','=','\\','\\','1',';','_','P','=','\\','\\','2',';','_','E','=','0',',','"',' ','-','e','"','t',' ','X','"',' ','-','e','"','s',',','\\','.','*',',','_','E','=','1',',','"',' ','-','e','"','\\',':',' ','X','"','`',';',' ','i','f',' ','[',' ','"','$','_','E','"',' ','=',' ','1',' ',']',';',' ','t','h','e','n',' ','e','c','h','o',' ','-','e','c','h','o',' ','I','n','v','a','l','i','d',' ','f','i','l','e',' ','l','i','n','k',';',' ','e','l','i','f',' ','[',' ','-','z',' ','"','$','_','H','"',' ','-','o',' ','"','$','_','H','"',' ','=',' ','l','o','c','a','l','h','o','s','t',' ','-','o',' ','"','$','_','H','"',' ','=',' ','$','H','O','S','T','N','A','M','E',' ',']',';',' ','t','h','e','n',' ','e','c','h','o',' ','"','\\',':','e',' ','$','_','P','"',';',' ','e','l','s','e',' ','e','c','h','o',' ','-','e','c','h','o',' ','C','a','n','n','o','t',' ','o','p','e','n',' ','r','e','m','o','t','e',' ','f','i','l','e',' ','o','n',' ','"','$','_','H','"',';',' ','f','i', - 0, + "LESS_OSC8_OPEN_ANY\0\201" +#ifdef LIBEXECDIR + "-" LIBEXECDIR "/less-osc8-open" +#else + "-less-osc8-open" +#endif + "\0" }; /* @@ -317,6 +319,9 @@ static struct tablelist *list_ecmd_tables = NULL; static struct tablelist *list_var_tables = NULL; static struct tablelist *list_sysvar_tables = NULL; +#if USERFILE +static struct tablelist * find_stop_table(struct tablelist *t); +#endif /* * Expand special key abbreviations in a command table. @@ -335,7 +340,7 @@ static void expand_special_keys(unsigned char *table, size_t len) * Rewrite each command in the table with any * special key abbreviations expanded. */ - for (to = fm; *fm != '\0'; ) + for (to = fm; fm < table + len && *fm != '\0'; ) { if (*fm != SK_SPECIAL_KEY) { @@ -352,7 +357,7 @@ static void expand_special_keys(unsigned char *table, size_t len) * output by the special key on this terminal. */ repl = special_key_str(fm[1]); - klen = fm[2] & 0377; + klen = fm[2]; fm += klen; if (repl == NULL || strlen(repl) > klen) repl = "\377"; @@ -367,10 +372,10 @@ static void expand_special_keys(unsigned char *table, size_t len) while (to <= fm) *to++ = A_SKIP; fm++; - a = *fm++ & 0377; + a = *fm++; if (a & A_EXTRA) { - while (*fm++ != '\0') + while (fm < table + len && *fm++ != '\0') continue; } } @@ -404,12 +409,15 @@ public void expand_cmd_tables(void) */ public void init_cmds(void) { + struct tablelist *t; + unsigned char *udflt_vartable = (unsigned char *) dflt_vartable; + /* * Add the default command tables. */ add_fcmd_table(cmdtable, sizeof(cmdtable)); add_ecmd_table(edittable, sizeof(edittable)); - add_sysvar_table(dflt_vartable, sizeof(dflt_vartable)); + add_sysvar_table(udflt_vartable, sizeof(dflt_vartable)); #if USERFILE #ifdef BINDIR /* For backwards compatibility */ /* Try to add tables in the OLD system lesskey file. */ @@ -449,6 +457,16 @@ public void init_cmds(void) add_content_table(lesskey_content, "LESSKEY_CONTENT_SYSTEM", TRUE); add_content_table(lesskey_content, "LESSKEY_CONTENT", FALSE); + + /* + * If any command table contains a #stop directive, discard all other tables. + */ + t = find_stop_table(list_fcmd_tables); + if (t != NULL) + { + t->t_next = NULL; + list_fcmd_tables = t; + } #endif /* USERFILE */ } @@ -555,7 +573,9 @@ public void add_sysvar_table(unsigned char *buf, size_t len) */ static int mouse_wheel_down(void) { - return ((mousecap == OPT_ONPLUS) ? A_B_MOUSE : A_F_MOUSE); + if (!(emouse & EMOUSE_VSCROLL)) + return A_NOACTION; + return mouse_reverse ? A_B_MOUSE : A_F_MOUSE; } /* @@ -563,7 +583,29 @@ static int mouse_wheel_down(void) */ static int mouse_wheel_up(void) { - return ((mousecap == OPT_ONPLUS) ? A_F_MOUSE : A_B_MOUSE); + if (!(emouse & EMOUSE_VSCROLL)) + return A_NOACTION; + return mouse_reverse ? A_F_MOUSE : A_B_MOUSE; +} + +/* + * Return action for a mouse wheel left event. + */ +static int mouse_wheel_left(void) +{ + if (!(emouse & EMOUSE_HSCROLL)) + return A_NOACTION; + return mouse_reverse ? A_R_MOUSE : A_L_MOUSE; +} + +/* + * Return action for a mouse wheel right event. + */ +static int mouse_wheel_right(void) +{ + if (!(emouse & EMOUSE_HSCROLL)) + return A_NOACTION; + return mouse_reverse ? A_L_MOUSE : A_R_MOUSE; } /* @@ -571,32 +613,48 @@ static int mouse_wheel_up(void) */ static int mouse_button_left(int x, int y, lbool down, lbool drag) { + static int last_drag_x = -1; static int last_drag_y = -1; static int last_click_y = -1; if (down && !drag) { + last_drag_x = x; last_drag_y = last_click_y = y; } - if (allow_drag && drag && last_drag_y >= 0) + if (drag) { - /* Drag text up/down */ - if (y > last_drag_y) - { - cmd_exec(); - backward(y - last_drag_y, FALSE, FALSE, FALSE); - last_drag_y = y; - } else if (y < last_drag_y) - { + if ((emouse & EMOUSE_HDRAG) && last_drag_x >= 0 && x != last_drag_x) { + /* Drag text left/right */ + pos_rehead(FALSE); + if (hshift < x - last_drag_x) + hshift = 0; + else + hshift -= x - last_drag_x; + screen_trashed(); cmd_exec(); - forward(last_drag_y - y, FALSE, FALSE, FALSE); - last_drag_y = y; + last_drag_x = x; } - } else if (!down) + if ((emouse & EMOUSE_VDRAG) && last_drag_y >= 0) { + /* Drag text up/down */ + if (y > last_drag_y) + { + cmd_exec(); + backward(y - last_drag_y, FALSE, FALSE, FALSE); + last_drag_y = y; + } else if (y < last_drag_y) + { + cmd_exec(); + forward(last_drag_y - y, FALSE, FALSE, FALSE); + last_drag_y = y; + } + } + } else if ((emouse & EMOUSE_LCLICK) && !down) { #if OSC8_LINK if (secure_allow(SF_OSC8_OPEN)) { + cmd_exec(); if (osc8_click(y, x)) return (A_NOACTION); } @@ -605,7 +663,8 @@ static int mouse_button_left(int x, int y, lbool down, lbool drag) #endif /* OSC8_LINK */ if (y < sc_height-1 && y == last_click_y) { - setmark('#', y); + cmd_exec(); + setmark('#', y, 0); screen_trashed(); } } @@ -622,9 +681,11 @@ static int mouse_button_right(int x, int y, lbool down, lbool drag) * {{ unlike mouse_button_left, we could return an action, * but keep it near mouse_button_left for readability. }} */ + if (!(emouse & EMOUSE_RCLICK)) + return (A_NOACTION); if (!down && y < sc_height-1) { - gomark('#'); + gomark('#', 0); screen_trashed(); } return (A_NOACTION); @@ -686,6 +747,10 @@ static int x11mouse_action(lbool skip) return mouse_wheel_down(); case X11MOUSE_WHEEL_UP: return mouse_wheel_up(); + case X11MOUSE_WHEEL_LEFT: + return mouse_wheel_left(); + case X11MOUSE_WHEEL_RIGHT: + return mouse_wheel_right(); case X11MOUSE_BUTTON1: case X11MOUSE_BUTTON2: case X11MOUSE_BUTTON3: @@ -720,6 +785,10 @@ static int x116mouse_action(lbool skip) return mouse_wheel_down(); case X11MOUSE_WHEEL_UP: return mouse_wheel_up(); + case X11MOUSE_WHEEL_LEFT: + return mouse_wheel_left(); + case X11MOUSE_WHEEL_RIGHT: + return mouse_wheel_right(); case X11MOUSE_BUTTON1: case X11MOUSE_BUTTON2: case X11MOUSE_BUTTON3: { @@ -776,82 +845,95 @@ static constant unsigned char * cmd_next_entry(constant unsigned char *entry, mu } /* + * Does a command table contain a #stop directive? + */ +static lbool table_has_stop(struct tablelist *t) +{ + constant unsigned char *entry = t->t_start; + + while (entry < t->t_end) + { + int action; + entry = cmd_next_entry(entry, &action, NULL, NULL); + if (action == A_END_LIST) + return TRUE; + } + return FALSE; +} + +/* + * Find the first command table with a #stop directive, if any. + */ +static struct tablelist * find_stop_table(struct tablelist *t) +{ + for (; t != NULL; t = t->t_next) + { + if (table_has_stop(t)) + return t; + } + return NULL; +} + +/* * Search a single command table for the command string in cmd. */ -static int cmd_search(constant char *cmd, constant unsigned char *table, constant unsigned char *endtable, constant unsigned char **extra, size_t *mlen) +static int cmd_decode(struct tablelist *tlist, constant char *cmd, lbool anchored, constant char **extra) { int action = A_INVALID; size_t match_len = 0; + constant unsigned char *table = NULL; + constant unsigned char *endtable; + if (extra != NULL) *extra = NULL; - while (table < endtable) + while (tlist != NULL) { int taction; constant unsigned char *textra; - size_t cmdlen; - size_t match = cmd_match((constant char *) table, cmd); - table = cmd_next_entry(table, &taction, &textra, &cmdlen); + size_t tcmdlen; + size_t tmatch; + if (table == NULL) + { + /* Beginning of table: set start/end pointers. */ + table = tlist->t_start; + endtable = tlist->t_end; + } + if (anchored) + tmatch = (strcmp((constant char *) table, cmd) == 0) ? strlen(cmd) : 0; + else + tmatch = cmd_match((constant char *) table, cmd); + table = cmd_next_entry(table, &taction, &textra, &tcmdlen); + if (table >= endtable) + { + /* End of table; move to next table. */ + tlist = tlist->t_next; + table = NULL; + } if (taction == A_END_LIST) - return (-action); - if (match >= match_len) + break; + if (tmatch >= match_len) { - if (match == cmdlen) /* (last chars of) cmd matches this table entry */ + if (tmatch == tcmdlen) { + /* (Last chars of) cmd matches this table entry. */ action = taction; if (extra != NULL) - *extra = textra; - } else if (match > 0 && action == A_INVALID) /* cmd is a prefix of this table entry */ + *extra = (constant char *) textra; + } else if (tmatch > 0 && (tmatch > match_len || action == A_INVALID)) { + /* cmd is a prefix of this table entry */ action = A_PREFIX; + if (extra != NULL) + *extra = NULL; } - match_len = match; - } - } - if (mlen != NULL) - *mlen = match_len; - return (action); -} - -/* - * Decode a command character and return the associated action. - * The "extra" string, if any, is returned in sp. - */ -static int cmd_decode(struct tablelist *tlist, constant char *cmd, constant char **sp) -{ - struct tablelist *t; - int action = A_INVALID; - size_t match_len = 0; - - /* - * Search for the cmd thru all the command tables. - * If we find it more than once, take the last one. - */ - *sp = NULL; - for (t = tlist; t != NULL; t = t->t_next) - { - constant unsigned char *tsp; - size_t mlen = match_len; - int taction = cmd_search(cmd, t->t_start, t->t_end, &tsp, &mlen); - if (mlen >= match_len) - { - match_len = mlen; - if (taction != A_INVALID) - { - *sp = (constant char *) tsp; - if (taction < 0) - { - action = -taction; - break; - } - action = taction; - } + match_len = tmatch; } } if (action == A_X11MOUSE_IN) action = x11mouse_action(FALSE); else if (action == A_X116MOUSE_IN) action = x116mouse_action(FALSE); - return (action); + return action; } /* @@ -859,7 +941,7 @@ static int cmd_decode(struct tablelist *tlist, constant char *cmd, constant char */ public int fcmd_decode(constant char *cmd, constant char **sp) { - return (cmd_decode(list_fcmd_tables, cmd, sp)); + return (cmd_decode(list_fcmd_tables, cmd, FALSE, sp)); } /* @@ -867,7 +949,7 @@ public int fcmd_decode(constant char *cmd, constant char **sp) */ public int ecmd_decode(constant char *cmd, constant char **sp) { - return (cmd_decode(list_ecmd_tables, cmd, sp)); + return (cmd_decode(list_ecmd_tables, cmd, FALSE, sp)); } /* @@ -894,6 +976,78 @@ public lbool parse_csl(lbool (*func)(constant char *word, size_t wlen, void *arg } /* + * Display error message for parse_csl_bitmap. + */ +static int csl_bitmap_error(constant char *pfx, constant char *type, size_t len, constant char *name) +{ + PARG parg; + size_t msglen = len + strlen(pfx) + strlen(type) + 32; + char *msg = ecalloc(msglen, sizeof(char)); + SNPRINTF4(msg, msglen, "%s: %s name \"%.*s\"", pfx, type, (int) len, name); + parg.p_string = msg; + error("%s", &parg); + free(msg); + return 0; +} + +/* + * Return the bit value of a csl_bitmap name. + */ +public int csl_bitmap_bit(constant char *name, size_t len, struct csl_bitmap_def *defs, int num_defs, constant char *pfx) +{ + int i; + int match = -1; + + for (i = 0; i < num_defs; i++) + { + if (strncmp(defs[i].bit_name, name, len) == 0) + { + if (match >= 0) /* name is ambiguous */ + return csl_bitmap_error(pfx, "ambiguous", len, name); + match = i; + } + } + if (match < 0) + return csl_bitmap_error(pfx, "invalid", len, name); + return defs[match].bit_value; +} + +/* State for parse_csl_bitmap. */ +struct csl_bitmap_info +{ + int bitmap; /* bitmap being constructed */ + struct csl_bitmap_def *def; /* array of name/value pairs */ + int num_defs; /* length of def array */ + constant char *pfx; /* prefix for error messages */ +}; + +/* + * Set a bit in a csl_bitmap_info based on a csl_bitmap name. + */ +static lbool csl_bitmap_set(constant char *word, size_t wlen, void *arg) +{ + struct csl_bitmap_info *info = (struct csl_bitmap_info *) arg; + info->bitmap |= csl_bitmap_bit(word, wlen, info->def, info->num_defs, info->pfx); + return TRUE; +} + +/* + * Parse a comma-separated list of csl_bitmap names and return + * the combined bitmap value. + */ +public int parse_csl_bitmap(constant char *str, struct csl_bitmap_def *defs, int num_defs, constant char *pfx) +{ + struct csl_bitmap_info info; + info.bitmap = 0; + info.def = defs; + info.num_defs = num_defs; + info.pfx = pfx; + if (!parse_csl(csl_bitmap_set, str, &info)) + return -1; + return info.bitmap; +} + +/* * Should we ignore the setting of an environment variable? */ static lbool word_no_match(constant char *word, size_t wlen, void *arg) @@ -920,13 +1074,13 @@ public constant char * lgetenv(constant char *var) if (ignore_env(var)) return (NULL); - a = cmd_decode(list_var_tables, var, &s); + a = cmd_decode(list_var_tables, var, TRUE, &s); if (a == EV_OK) return (s); s = getenv(var); if (s != NULL && *s != '\0') return (s); - a = cmd_decode(list_sysvar_tables, var, &s); + a = cmd_decode(list_sysvar_tables, var, TRUE, &s); if (a == EV_OK) return (s); return (NULL); diff --git a/defines.h.in b/defines.h.in index dc904f67a1e7..45d184b23384 100644 --- a/defines.h.in +++ b/defines.h.in @@ -410,6 +410,18 @@ /* Define HAVE_TIME_T if your system supports the "time_t" type. */ #undef HAVE_TIME_T +/* Define HAVE_TPARM2 if your terminfo library supports tparm with 2 + parameters. */ +#undef HAVE_TPARM2 + +/* Define HAVE_TPARM8 if your terminfo library supports tparm with 8 + parameters. */ +#undef HAVE_TPARM8 + +/* Define HAVE_TPARM9 if your terminfo library supports tparm with 9 + parameters. */ +#undef HAVE_TPARM9 + /* Define to 1 if you have the 'ttyname' function. */ #undef HAVE_TTYNAME @@ -25,13 +25,13 @@ public int fd0 = 0; extern lbool new_file; extern char *every_first_cmd; extern int force_open; -extern int is_tty; +extern lbool is_tty; extern int sigs; extern int hshift; extern int want_filesize; -extern int consecutive_nulls; extern int modelines; extern int show_preproc_error; +extern lbool read_error; extern IFILE curr_ifile; extern IFILE old_ifile; extern struct scrpos initial_scrpos; @@ -264,6 +264,7 @@ static void close_pipe(FILE *pipefd) int status; char *p; PARG parg; + int sig = 0; if (pipefd == NULL) return; @@ -290,18 +291,33 @@ static void close_pipe(FILE *pipefd) if (WIFEXITED(status)) { int s = WEXITSTATUS(status); - if (s != 0) + if (s == 0) + return; + if (s <= 128) { parg.p_int = s; error("Input preprocessor failed (status %d)", &parg); + return; } - return; + /* + * popen invoked the shell, which likely last ran a + * program that terminated due to a signal. + * Assume the longstanding tradition (allowed but not + * required by POSIX) of adding 128 to the signal. + * Many shells use last command optimization, i.e., + * they exec the last command instead of forking and + * waiting for it, and in that case the more-reliable + * WIFSIGNALED code below will be used. + */ + sig = s - 128; } #endif #if defined WIFSIGNALED && defined WTERMSIG if (WIFSIGNALED(status)) + sig = WTERMSIG(status); +#endif + if (sig != 0) { - int sig = WTERMSIG(status); if ( #ifdef SIGPIPE sig != SIGPIPE || @@ -313,7 +329,6 @@ static void close_pipe(FILE *pipefd) } return; } -#endif if (status != 0) { parg.p_int = status; @@ -361,11 +376,14 @@ static void close_file(void) * Save the current position so that we can return to * the same position if we edit this file again. */ - get_scrpos(&scrpos, TOP); - if (scrpos.pos != NULL_POSITION) + if (is_tty) { - store_pos(curr_ifile, &scrpos); - lastmark(); + get_scrpos(&scrpos, TOP); + if (scrpos.pos != NULL_POSITION) + { + store_pos(curr_ifile, &scrpos); + lastmark(); + } } /* * Close the file descriptor, unless it is a pipe. @@ -545,7 +563,7 @@ public int edit_ifile(IFILE ifile) } else { chflags |= CH_CANSEEK; - if (bin_file(f, &nread) && !force_open && !opened(ifile)) + if (bin_file(f, &nread) && is_tty && !force_open && !opened(ifile)) { /* * Looks like a binary file. @@ -611,7 +629,6 @@ public int edit_ifile(IFILE ifile) set_open(curr_ifile); /* File has been opened */ get_pos(curr_ifile, &initial_scrpos); ch_init(f, chflags, nread); - consecutive_nulls = 0; check_modelines(); if (!(chflags & CH_HELPFILE)) @@ -660,6 +677,7 @@ public int edit_ifile(IFILE ifile) #endif undo_osc8(); hshift = 0; + read_error = FALSE; if (strcmp(filename, FAKE_HELPFILE) && strcmp(filename, FAKE_EMPTYFILE)) { char *qfilename = shell_quote(filename); diff --git a/filename.c b/filename.c index ad1b4b3cf4a9..0c7f32f54f09 100644 --- a/filename.c +++ b/filename.c @@ -319,15 +319,13 @@ static void xcpy_char(xcpy *xp, char ch) static void xcpy_filename(xcpy *xp, constant char *str) { - /* If filename contains spaces, quote it - * to prevent edit_list from splitting it. */ - lbool quote = (strchr(str, ' ') != NULL); - if (quote) - xcpy_char(xp, openquote); - for (; *str != '\0'; str++) - xcpy_char(xp, *str); - if (quote) - xcpy_char(xp, closequote); + char *qstr = shell_quote(str); + char *s; + if (qstr == NULL) + return; + for (s = qstr; *s != '\0'; s++) + xcpy_char(xp, *s); + free(qstr); } static size_t fexpand_copy(constant char *fr, char *to) @@ -733,7 +731,11 @@ public char * lglob(constant char *afilename) } lessecho = lgetenv("LESSECHO"); if (isnullenv(lessecho)) +#ifdef LIBEXECDIR + lessecho = LIBEXECDIR "/lessecho"; +#else lessecho = "lessecho"; +#endif /* * Invoke lessecho, and read its output (a globbed list of filenames). */ diff --git a/forwback.c b/forwback.c index eef1d5de3847..570e41e195fc 100644 --- a/forwback.c +++ b/forwback.c @@ -17,8 +17,8 @@ #include "position.h" public lbool squished; -public int no_back_scroll = 0; -public int forw_prompt; +public lbool no_back_scroll = FALSE; +public lbool forw_prompt; public lbool first_time = TRUE; /* We're printing the first screen of output */ public int shell_lines = 1; /* soft_eof is set as end-of-file when a read attempt returns EOF. This can @@ -37,8 +37,9 @@ extern int back_scroll; extern lbool ignore_eoi; extern int header_lines; extern int header_cols; -extern int full_screen; +extern lbool full_screen; extern int stop_on_form_feed; +extern int past_eof; extern POSITION header_start_pos; extern lbool getting_one_screen; #if HILITE_SEARCH @@ -138,7 +139,7 @@ static POSITION forw_line_pfx(POSITION pos, int pfx, int skipeol) sc_width = pfx + line_pfx_width(); auto_wrap = 0; hshift = 0; - pos = forw_line_seg(pos, skipeol, FALSE, FALSE, NULL, NULL); + pos = forw_line_seg(pos, skipeol, FALSE, FALSE, FALSE, TRUE, NULL, NULL); sc_width = save_sc_width; auto_wrap = save_auto_wrap; hshift = save_hshift; @@ -226,6 +227,8 @@ public void forw(int n, POSITION pos, lbool force, lbool only_last, lbool to_new if (pos != NULL_POSITION) pos = after_header_pos(pos); + if (past_eof) + force = TRUE; squish_check(); /* @@ -241,7 +244,7 @@ public void forw(int n, POSITION pos, lbool force, lbool only_last, lbool to_new (forw_scroll >= 0 && n > forw_scroll && n != sc_height-1); if (!do_repaint) { - if (top_scroll && n >= sc_height - 1 && pos != ch_length()) + if (top_scroll && n >= sc_height - 1 && pos != NULL_POSITION && pos != ch_length()) { /* * Start a new screen. @@ -303,18 +306,25 @@ public void forw(int n, POSITION pos, lbool force, lbool only_last, lbool to_new /* * End of file: stop here unless the top line * is still empty, or "force" is true. - * Even if force is true, stop when the last - * line in the file reaches the top of screen. */ soft_eof = opos; - linepos = opos; - if (ABORT_SIGS() || - (!force && position(TOP) != NULL_POSITION) || - (!empty_lines(0, 0) && !empty_lines(1, 1) && empty_lines(2, sc_height-1))) + linepos = (opos == ch_zero()) ? NULL_POSITION : opos; + if (ABORT_SIGS() || !force) { pos = opos; break; } + /* + * Even if force is true, stop when the last + * line in the file reaches the top of screen. + * Check for 3 non-empty lines at top of screen. + * The first will be shifted away by the add_forw_pos() + * after this loop; the other two are the start and end of + * the single line that we want to retain at top of screen. + */ + if (!first_line && sc_height >= 3 && empty_lines(3, sc_height-1) && + !empty_lines(0, 0) && !empty_lines(1, 1) && !empty_lines(2, 2)) + break; } } /* @@ -355,7 +365,7 @@ public void forw(int n, POSITION pos, lbool force, lbool only_last, lbool to_new put_line(TRUE); if (do_stop_on_form_feed && !do_repaint && line_is_ff() && position(TOP) != NULL_POSITION) break; - forw_prompt = 1; + forw_prompt = TRUE; } if (!first_line) add_forw_pos(pos, FALSE); @@ -382,6 +392,8 @@ public void back(int n, POSITION pos, lbool force, lbool only_last, lbool to_new lbool newline; squish_check(); + if (past_eof) + force = TRUE; do_repaint = (n > get_back_scroll() || (only_last && n > sc_height-1) || header_lines > 0); while (--n >= 0) @@ -397,7 +409,18 @@ public void back(int n, POSITION pos, lbool force, lbool only_last, lbool to_new /* * Beginning of file: stop here unless "force" is true. */ - if (!force) + if (ABORT_SIGS() || !force) + break; + /* + * Even if force is true, stop when the first + * line in the file reaches the bottom of the screen. + * Check for 2 non-empty lines at bottom of screen. + * These are the start and end of the single line that + * we want to retain at bottom of screen. + */ + if (sc_height >= 3 && empty_lines(0, sc_height-3) && + !empty_lines(sc_height-1, sc_height-1) && + !empty_lines(sc_height-2, sc_height-2)) break; } if (pos != after_header_pos(pos)) @@ -453,6 +476,8 @@ public void forward(int n, lbool force, lbool only_last, lbool to_newline) return; } + if (past_eof) + force = TRUE; pos = position(BOTTOM_PLUS_ONE); if (pos == NULL_POSITION && (!force || empty_lines(2, sc_height-1))) { @@ -490,6 +515,8 @@ public void backward(int n, lbool force, lbool only_last, lbool to_newline) { POSITION pos; + if (past_eof) + force = TRUE; pos = position(TOP); if (pos == NULL_POSITION && (!force || position(BOTTOM) == 0)) { @@ -12,7 +12,7 @@ public void scrsize(void); public void screen_size_changed(void); public constant char * special_key_str(int key); public void init_win_colors(void); -public void get_term(); +public void get_term(void); public void init_mouse(void); public void deinit_mouse(void); public void suspend_screen(void); @@ -43,8 +43,10 @@ public void at_switch(int attr); public lbool is_at_equiv(int attr1, int attr2); public int apply_at_specials(int attr); public void putbs(void); +public void win32_enqueue(int ch); public void WIN32ungetch(int ch); -public lbool win32_kbhit2(lbool no_queued); +public void win32_clear_queue(void); +public lbool win32_kbhit2(char *pch); public lbool win32_kbhit(void); public int WIN32getch(void); public void win32_getch_clear(void); @@ -76,8 +78,8 @@ public lbool binary_char(LWCHAR c); public lbool control_char(LWCHAR c); public constant char * prchar(LWCHAR c); public constant char * prutfchar(LWCHAR ch); -public int utf_len(char ch); -public lbool is_utf8_well_formed(constant char *ss, int slen); +public int utf_len(char ach); +public lbool is_utf8_well_formed(constant char *ssa, int slen); public void utf_skip_to_lead(constant char **pp, constant char *limit); public LWCHAR get_wchar(constant char *sp); public void put_wchar(mutable char **pp, LWCHAR ch); @@ -120,8 +122,8 @@ public void ungetcc_back(char c); public void ungetcc_end_command(void); public void ungetsc(constant char *s); public char peekcc(void); -public void start_ignoring_input(); -public void stop_ignoring_input(); +public void start_ignoring_input(void); +public void stop_ignoring_input(void); public lbool is_ignoring_input(int action); public void commands(void); public size_t cvt_length(size_t len, int ops); @@ -136,6 +138,8 @@ public void add_sysvar_table(unsigned char *buf, size_t len); public int fcmd_decode(constant char *cmd, constant char **sp); public int ecmd_decode(constant char *cmd, constant char **sp); public lbool parse_csl(lbool (*func)(constant char *word, size_t wlen, void *arg), constant char *str, void *arg); +public int csl_bitmap_bit(constant char *name, size_t len, struct csl_bitmap_def *defs, int num_defs, constant char *pfx); +public int parse_csl_bitmap(constant char *str, struct csl_bitmap_def *defs, int num_defs, constant char *pfx); public constant char * lgetenv(constant char *var); public constant char * lgetenv_ext(constant char *var, unsigned char *env_buf, size_t env_buf_len); public lbool isnullenv(constant char *s); @@ -218,7 +222,7 @@ public void *get_altpipe(IFILE ifile); public void set_altfilename(IFILE ifile, char *altfilename); public char * get_altfilename(IFILE ifile); public void if_dump(void); -public POSITION forw_line_seg(POSITION curr_pos, lbool skipeol, lbool rscroll, lbool nochop, POSITION *p_linepos, lbool *p_newline); +public POSITION forw_line_seg(POSITION curr_pos, lbool skipeol, lbool rscroll, lbool nochop, lbool full_pad, lbool rforw, POSITION *p_linepos, lbool *p_newline); public POSITION forw_line(POSITION curr_pos, POSITION *p_linepos, lbool *p_newline); public POSITION back_line(POSITION curr_pos, lbool *p_newline); public void set_attnpos(POSITION pos); @@ -237,7 +241,7 @@ public lbool is_line_contig_pos(POSITION pos); public void set_line_contig_pos(POSITION pos); public void prewind(lbool contig); public void plinestart(POSITION pos); -public int line_pfx_width(void); +public unsigned line_pfx_width(void); public void pshift_all(void); public int pwidth(LWCHAR ch, int a, LWCHAR prev_ch, int prev_a); public void savec(void); @@ -253,7 +257,7 @@ public int pappend_b(char c, POSITION pos, lbool before_pendc); public int pappend(char c, POSITION pos); public lbool line_is_ff(void); public int pflushmbc(void); -public void pdone(lbool endline, lbool chopped, lbool forw); +public void pdone(lbool endline, lbool chopped, lbool forw, lbool full_pad); public int col_from_pos(POSITION linepos, POSITION spos, POSITION saved_pos, int saved_col); public POSITION pos_from_col(POSITION linepos, int col, POSITION saved_pos, int saved_col); public void set_attr_line(int a); @@ -265,7 +269,7 @@ public POSITION forw_raw_line_len(POSITION curr_pos, size_t read_len, constant c public POSITION forw_raw_line(POSITION curr_pos, constant char **linep, size_t *line_lenp); public POSITION back_raw_line(POSITION curr_pos, constant char **linep, size_t *line_lenp); public int skip_columns(int cols, constant char **linep, size_t *line_lenp); -public void load_line(constant char *str); +public void load_line(constant char *str, int attr, int reserve); public int longest_line_width(void); public int rrshift(void); public int set_color_map(int attr, constant char *colorstr); @@ -282,10 +286,10 @@ public int pipe_mark(char c, constant char *cmd); public int pipe_data(constant char *cmd, POSITION spos, POSITION epos); public void init_mark(void); public lbool badmark(char c); -public void setmark(char c, int where); +public void setmark(char c, int where, LINENUM linenum); public void clrmark(char c); public void lastmark(void); -public void gomark(char c); +public void gomark(char c, int sline); public POSITION markpos(char c); public char posmark(POSITION pos); public void unmark(IFILE ifile); @@ -306,6 +310,7 @@ public void opt_t(int type, constant char *s); public void opt__T(int type, constant char *s); public void opt_p(int type, constant char *s); public void opt__P(int type, constant char *s); +public void opt_end_prompt(int type, constant char *s); public void opt_autosave(int type, constant char *s); public void opt_b(int type, constant char *s); public void opt_i(int type, constant char *s); @@ -318,7 +323,8 @@ public void opt_rscroll(int type, constant char *s); public void opt_query(int type, constant char *s); public void opt_match_shift(int type, constant char *s); public void calc_match_shift(void); -public void opt_mousecap(int type, constant char *s); +public void opt_emouse(int type, constant char *s); +public void opt_mouse(int type, constant char *s); public void opt_wheel_lines(int type, constant char *s); public void opt_linenum_width(int type, constant char *s); public void opt_status_col_width(int type, constant char *s); @@ -326,6 +332,7 @@ public void opt_filesize(int type, constant char *s); public void opt_first_cmd_at_prompt(int type, constant char *s); public void opt_intr(int type, constant char *s); public void opt_header(int type, constant char *s); +public void opt_hilite_target(int type, constant char *s); public void opt_search_type(int type, constant char *s); public void opt_nosearch_headers(int type, constant char *s); public void opt_nosearch_header_lines(int type, constant char *s); @@ -367,6 +374,7 @@ public int percentage(POSITION num, POSITION den); public POSITION percent_pos(POSITION pos, int percent, long fraction); public int os9_signal(int type, RETSIGTYPE (*handler)()); public void sleep_ms(int ms); +public void put_line_hilite(lbool forw_scroll, lbool target); public void put_line(lbool forw_scroll); public void flush(void); public void set_output(int fd, lbool no_term_init); @@ -393,17 +401,22 @@ public void pos_init(void); public int onscreen(POSITION pos); public lbool empty_screen(void); public lbool empty_lines(int s, int e); +public void get_scrpos_pos(struct scrpos *scrpos, int where, POSITION pos); public void get_scrpos(struct scrpos *scrpos, int where); public int sindex_from_sline(int sline); -public void pos_rehead(void); +public POSITION beginning_of_line(POSITION tpos); +public void pos_rehead(lbool adj_hshift); public void init_prompt(void); public constant char * pr_expand(constant char *proto); public constant char * eq_message(void); public constant char * pr_string(void); +public constant char * end_pr_string(void); public constant char * wait_message(void); public void init_search(void); public int get_cvt_ops(int search_type); +public constant char* prev_pattern_text(void); public void repaint_hilite(lbool on); +public void draw_target_attn(lbool hilite); public void clear_attn(void); public void undo_search(lbool clear); public lbool undo_osc8(void); @@ -1,4 +1,4 @@ -/* This file was generated by mkhelp.pl from less.hlp at 17:46 on 2026/1/29 */ +/* This file was generated by mkhelp.pl from less.hlp at 23:54 on 2026/5/30 */ #include "less.h" constant char helpdata[] = { '\n', @@ -55,7 +55,7 @@ constant char helpdata[] = { ' ',' ','E','S','C','-','U',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','C','l','e','a','r',' ','s','e','a','r','c','h',' ','h','i','g','h','l','i','g','h','t','i','n','g','.','\n', ' ',' ','&','_','\b','p','_','\b','a','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','n',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','D','i','s','p','l','a','y',' ','o','n','l','y',' ','m','a','t','c','h','i','n','g',' ','l','i','n','e','s','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\n', -'\t','\t','S','e','a','r','c','h',' ','i','s',' ','c','a','s','e','-','s','e','n','s','i','t','i','v','e',' ','u','n','l','e','s','s',' ','c','h','a','n','g','e','d',' ','w','i','t','h',' ','-','i',' ','o','r',' ','-','I','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ','S','e','a','r','c','h',' ','i','s',' ','c','a','s','e','-','s','e','n','s','i','t','i','v','e',' ','u','n','l','e','s','s',' ','c','h','a','n','g','e','d',' ','w','i','t','h',' ','-','i',' ','o','r',' ','-','I','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ','A',' ','s','e','a','r','c','h',' ','p','a','t','t','e','r','n',' ','m','a','y',' ','b','e','g','i','n',' ','w','i','t','h',' ','o','n','e',' ','o','r',' ','m','o','r','e',' ','o','f',':','\n', ' ',' ',' ',' ',' ',' ',' ',' ','^','N',' ','o','r',' ','!',' ',' ','S','e','a','r','c','h',' ','f','o','r',' ','N','O','N','-','m','a','t','c','h','i','n','g',' ','l','i','n','e','s','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ','^','E',' ','o','r',' ','*',' ',' ','S','e','a','r','c','h',' ','m','u','l','t','i','p','l','e',' ','f','i','l','e','s',' ','(','p','a','s','s',' ','t','h','r','u',' ','E','N','D',' ','O','F',' ','F','I','L','E',')','.','\n', @@ -84,11 +84,11 @@ constant char helpdata[] = { ' ',' ',' ',' ',' ',' ',' ',' ','E','a','c','h',' ','"','f','i','n','d',' ','o','p','e','n',' ','b','r','a','c','k','e','t','"',' ','c','o','m','m','a','n','d',' ','g','o','e','s',' ','b','a','c','k','w','a','r','d',' ','t','o',' ','t','h','e',' ','o','p','e','n',' ','b','r','a','c','k','e','t',' ','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','m','a','t','c','h','i','n','g',' ','t','h','e',' ','(','_','\b','N','-','t','h',')',' ','c','l','o','s','e',' ','b','r','a','c','k','e','t',' ','i','n',' ','t','h','e',' ','b','o','t','t','o','m',' ','l','i','n','e','.','\n', '\n', -' ',' ','m','_','\b','<','_','\b','l','_','\b','e','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','>',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','M','a','r','k',' ','t','h','e',' ','c','u','r','r','e','n','t',' ','t','o','p',' ','l','i','n','e',' ','w','i','t','h',' ','<','l','e','t','t','e','r','>','.','\n', -' ',' ','M','_','\b','<','_','\b','l','_','\b','e','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','>',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','M','a','r','k',' ','t','h','e',' ','c','u','r','r','e','n','t',' ','b','o','t','t','o','m',' ','l','i','n','e',' ','w','i','t','h',' ','<','l','e','t','t','e','r','>','.','\n', -' ',' ','\'','_','\b','<','_','\b','l','_','\b','e','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','>',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','G','o',' ','t','o',' ','a',' ','p','r','e','v','i','o','u','s','l','y',' ','m','a','r','k','e','d',' ','p','o','s','i','t','i','o','n','.','\n', -' ',' ','\'','\'',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','G','o',' ','t','o',' ','t','h','e',' ','p','r','e','v','i','o','u','s',' ','p','o','s','i','t','i','o','n','.','\n', -' ',' ','^','X','^','X',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','a','m','e',' ','a','s',' ','\'','.','\n', +' ',' ','m','_','\b','<','_','\b','l','_','\b','e','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','>',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','M','a','r','k',' ','t','h','e',' ','t','o','p',' ','l','i','n','e',' ','(','o','r',' ','l','i','n','e',' ','_','\b','N',')',' ','w','i','t','h',' ','<','l','e','t','t','e','r','>','.','\n', +' ',' ','M','_','\b','<','_','\b','l','_','\b','e','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','>',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','M','a','r','k',' ','t','h','e',' ','b','o','t','t','o','m',' ','l','i','n','e',' ','(','o','r',' ','l','i','n','e',' ','_','\b','N',')',' ','w','i','t','h',' ','<','l','e','t','t','e','r','>','.','\n', +' ',' ','\'','_','\b','<','_','\b','l','_','\b','e','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','>',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','G','o',' ','t','o',' ','a',' ','p','r','e','v','i','o','u','s','l','y',' ','m','a','r','k','e','d',' ','p','o','s','i','t','i','o','n',' ','(','p','u','t',' ','o','n',' ','p','o','s','i','t','i','o','n',' ','_','\b','N',')','.','\n', +' ',' ','\'','\'',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','G','o',' ','t','o',' ','t','h','e',' ','p','r','e','v','i','o','u','s',' ','p','o','s','i','t','i','o','n','.','\n', +' ',' ','^','X','^','X',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','*',' ',' ','S','a','m','e',' ','a','s',' ','\'','.','\n', ' ',' ','E','S','C','-','m','_','\b','<','_','\b','l','_','\b','e','_','\b','t','_','\b','t','_','\b','e','_','\b','r','_','\b','>',' ',' ',' ',' ',' ',' ',' ',' ','C','l','e','a','r',' ','a',' ','m','a','r','k','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','-','\n', ' ',' ',' ',' ',' ',' ',' ',' ','A',' ','m','a','r','k',' ','i','s',' ','a','n','y',' ','u','p','p','e','r','-','c','a','s','e',' ','o','r',' ','l','o','w','e','r','-','c','a','s','e',' ','l','e','t','t','e','r','.','\n', @@ -205,9 +205,9 @@ constant char helpdata[] = { ' ',' ','-','V',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','v','e','r','s','i','o','n','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','i','s','p','l','a','y',' ','t','h','e',' ','v','e','r','s','i','o','n',' ','n','u','m','b','e','r',' ','o','f',' ','"','l','e','s','s','"','.','\n', ' ',' ','-','w',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','h','i','l','i','t','e','-','u','n','r','e','a','d','\n', -' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','H','i','g','h','l','i','g','h','t',' ','f','i','r','s','t',' ','n','e','w',' ','l','i','n','e',' ','a','f','t','e','r',' ','f','o','r','w','a','r','d','-','s','c','r','e','e','n','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','H','i','g','h','l','i','g','h','t',' ','f','i','r','s','t',' ','n','e','w',' ','l','i','n','e',' ','a','f','t','e','r',' ','f','u','l','l',' ','s','c','r','e','e','n',' ','m','o','v','e','m','e','n','t','.','\n', ' ',' ','-','W',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','H','I','L','I','T','E','-','U','N','R','E','A','D','\n', -' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','H','i','g','h','l','i','g','h','t',' ','f','i','r','s','t',' ','n','e','w',' ','l','i','n','e',' ','a','f','t','e','r',' ','a','n','y',' ','f','o','r','w','a','r','d',' ','m','o','v','e','m','e','n','t','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','H','i','g','h','l','i','g','h','t',' ','f','i','r','s','t',' ','n','e','w',' ','l','i','n','e',' ','a','f','t','e','r',' ','a','n','y',' ','m','o','v','e','m','e','n','t','.','\n', ' ',' ','-','x',' ','[','_','\b','N','[',',','.','.','.',']',']',' ',' ','-','-','t','a','b','s','=','[','_','\b','N','[',',','.','.','.',']',']','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','t','a','b',' ','s','t','o','p','s','.','\n', ' ',' ','-','X',' ',' ','.','.','.','.','.','.','.','.',' ',' ','-','-','n','o','-','i','n','i','t','\n', @@ -225,6 +225,10 @@ constant char helpdata[] = { '\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','a','u','t','o','s','a','v','e','=','[','_','\b','m','_','\b','/','_','\b','!','_','\b','*',']','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','A','c','t','i','o','n','s',' ','w','h','i','c','h',' ','c','a','u','s','e',' ','t','h','e',' ','h','i','s','t','o','r','y',' ','f','i','l','e',' ','t','o',' ','b','e',' ','s','a','v','e','d','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','e','m','o','u','s','e','=','[','_','\b','v','_','\b','s','_','\b','c','_','\b','r','_','\b','o','_','\b','l','_','\b','l',',','_','\b','v','_','\b','d','_','\b','r','_','\b','a','_','\b','g',',','_','\b','h','_','\b','s','_','\b','c','_','\b','r','_','\b','o','_','\b','l','_','\b','l',',','_','\b','h','_','\b','d','_','\b','r','_','\b','a','_','\b','g',',','_','\b','l','_','\b','c','_','\b','l','_','\b','i','_','\b','c','_','\b','k',',','_','\b','r','_','\b','c','_','\b','l','_','\b','i','_','\b','c','_','\b','k',']','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','n','a','b','l','e',' ','m','o','u','s','e',' ','f','e','a','t','u','r','e','s','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','e','n','d','-','p','r','o','m','p','t','=','[','_','\b','s','_','\b','t','_','\b','r','_','\b','i','_','\b','n','_','\b','g',']','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','t','r','i','n','g',' ','t','o',' ','b','e',' ','p','r','i','n','t','e','d',' ','a','f','t','e','r',' ','e','r','a','s','i','n','g',' ','t','h','e',' ','p','r','o','m','p','t','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','e','x','i','t','-','f','o','l','l','o','w','-','o','n','-','c','l','o','s','e','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','x','i','t',' ','F',' ','c','o','m','m','a','n','d',' ','o','n',' ','a',' ','p','i','p','e',' ','w','h','e','n',' ','w','r','i','t','e','r',' ','c','l','o','s','e','s',' ','p','i','p','e','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','f','i','l','e','-','s','i','z','e','\n', @@ -235,6 +239,8 @@ constant char helpdata[] = { ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','t','o','p',' ','s','c','r','o','l','l','i','n','g',' ','w','h','e','n',' ','a',' ','f','o','r','m',' ','f','e','e','d',' ','c','h','a','r','a','c','t','e','r',' ','i','s',' ','r','e','a','c','h','e','d','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','h','e','a','d','e','r','=','[','_','\b','L','[',',','_','\b','C','[',',','_','\b','N',']',']',']','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','U','s','e',' ','_','\b','L',' ','l','i','n','e','s',' ','(','s','t','a','r','t','i','n','g',' ','a','t',' ','l','i','n','e',' ','_','\b','N',')',' ','a','n','d',' ','_','\b','C',' ','c','o','l','u','m','n','s',' ','a','s',' ','h','e','a','d','e','r','s','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','h','i','l','i','t','e','-','t','a','r','g','e','t','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','H','i','g','h','l','i','g','h','t',' ','t','h','e',' ','t','a','r','g','e','t',' ','l','i','n','e','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','i','n','c','s','e','a','r','c','h','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','a','r','c','h',' ','f','i','l','e',' ','a','s',' ','e','a','c','h',' ','p','a','t','t','e','r','n',' ','c','h','a','r','a','c','t','e','r',' ','i','s',' ','t','y','p','e','d',' ','i','n','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','i','n','t','r','=','[','_','\b','C',']','\n', @@ -250,7 +256,7 @@ constant char helpdata[] = { ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','m','o','d','e','l','i','n','e','s','=','[','_','\b','N',']','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','R','e','a','d',' ','_','\b','N',' ','l','i','n','e','s',' ','f','r','o','m',' ','t','h','e',' ','i','n','p','u','t',' ','f','i','l','e',' ','a','n','d',' ','l','o','o','k',' ','f','o','r',' ','v','i','m',' ','m','o','d','e','l','i','n','e','s','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','m','o','u','s','e','\n', -' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','n','a','b','l','e',' ','m','o','u','s','e',' ','i','n','p','u','t','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','E','n','a','b','l','e',' ','m','o','u','s','e',' ','c','l','i','c','k','i','n','g',' ','a','n','d',' ','v','e','r','t','i','c','a','l',' ','s','c','r','o','l','l','i','n','g','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','n','o','-','e','d','i','t','-','w','a','r','n','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','w','a','r','n',' ','w','h','e','n',' ','u','s','i','n','g',' ','v',' ','c','o','m','m','a','n','d',' ','o','n',' ','a',' ','f','i','l','e',' ','o','p','e','n','e','d',' ','v','i','a',' ','L','E','S','S','O','P','E','N','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','n','o','-','k','e','y','p','a','d','\n', @@ -279,6 +285,8 @@ constant char helpdata[] = { ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','d','e','f','a','u','l','t',' ','o','p','t','i','o','n','s',' ','f','o','r',' ','e','v','e','r','y',' ','s','e','a','r','c','h','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','s','h','o','w','-','p','r','e','p','r','o','c','-','e','r','r','o','r','s','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','i','s','p','l','a','y',' ','a',' ','m','e','s','s','a','g','e',' ','i','f',' ','p','r','e','p','r','o','c','e','s','s','o','r',' ','e','x','i','t','s',' ','w','i','t','h',' ','a','n',' ','e','r','r','o','r',' ','s','t','a','t','u','s','.','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','p','a','s','t','-','e','o','f','\n', +' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','c','r','o','l','l','i','n','g',' ','c','o','m','m','a','n','d','s',' ','c','o','n','t','i','n','u','e',' ','p','a','s','t',' ','e','n','d',' ','o','f',' ','f','i','l','e','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','p','r','o','c','-','b','a','c','k','s','p','a','c','e','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','P','r','o','c','e','s','s',' ','b','a','c','k','s','p','a','c','e','s',' ','f','o','r',' ','b','o','l','d','/','u','n','d','e','r','l','i','n','e','.','\n', ' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','P','R','O','C','-','B','A','C','K','S','P','A','C','E','\n', @@ -80,7 +80,7 @@ static void init_status_col(POSITION base_pos, POSITION disp_pos, POSITION edisp * a line. The new position is the position of the first character * of the NEXT line. The line obtained is the line starting at curr_pos. */ -public POSITION forw_line_seg(POSITION curr_pos, lbool skipeol, lbool rscroll, lbool nochop, POSITION *p_linepos, lbool *p_newline) +public POSITION forw_line_seg(POSITION curr_pos, lbool skipeol, lbool rscroll, lbool nochop, lbool full_pad, lbool rforw, POSITION *p_linepos, lbool *p_newline) { POSITION base_pos; POSITION new_pos; @@ -245,7 +245,7 @@ get_forw_line: } while (c != '\n' && c != EOI); new_pos = ch_tell(); endline = TRUE; - quit_if_one_screen = FALSE; + quit_if_one_screen = 0; chopped = TRUE; } else { @@ -306,7 +306,7 @@ get_forw_line: pappend_b(' ', ch_tell()-1, TRUE); } #endif - pdone(endline, rscroll && chopped, TRUE); + pdone(endline, rscroll && chopped, rforw, full_pad); #if HILITE_SEARCH if (is_filtered(base_pos)) @@ -345,7 +345,7 @@ get_forw_line: public POSITION forw_line(POSITION curr_pos, POSITION *p_linepos, lbool *p_newline) { - return forw_line_seg(curr_pos, (chop_line() || hshift > 0), TRUE, FALSE, p_linepos, p_newline); + return forw_line_seg(curr_pos, (chop_line() || hshift > 0), TRUE, FALSE, FALSE, TRUE, p_linepos, p_newline); } /* @@ -501,7 +501,7 @@ get_back_line: { endline = TRUE; chopped = TRUE; - quit_if_one_screen = FALSE; + quit_if_one_screen = 0; edisp_pos = new_pos; break; } @@ -568,7 +568,7 @@ get_back_line: } } - pdone(endline, chopped, FALSE); + pdone(endline, chopped, FALSE, FALSE); #if HILITE_SEARCH if (is_filtered(base_pos)) @@ -20,6 +20,9 @@ extern lbool squished; extern int sc_width, sc_height; extern int show_attn; extern int top_scroll; +extern int quit_if_one_screen; +extern lbool one_screen; +extern lbool full_screen; extern POSITION header_start_pos; /* @@ -188,15 +191,15 @@ static void after_header_message(void) { #if HAVE_TIME #define MSG_FREQ 1 /* seconds */ - static time_type last_msg = (time_type) 0; - time_type now = get_time(); - if (now < last_msg + MSG_FREQ) - return; - last_msg = now; + static time_type last_msg = (time_type) 0; + time_type now = get_time(); + if (now < last_msg + MSG_FREQ) + return; + last_msg = now; #endif - lbell(); - /* {{ This message displays before the file text is updated, which is not a good UX. }} */ - /** error("Cannot display text before header; use --header=- to disable header", NULL_PARG); */ + lbell(); + /* {{ This message displays before the file text is updated, which is not a good UX. }} */ + /** error("Cannot display text before header; use --header=- to disable header", NULL_PARG); */ } /* @@ -210,8 +213,8 @@ public POSITION after_header_pos(POSITION pos) { if (header_start_pos != NULL_POSITION && pos < header_start_pos) { - after_header_message(); - pos = header_start_pos; + after_header_message(); + pos = header_start_pos; } return pos; } @@ -235,6 +238,14 @@ public void jump_loc(POSITION pos, int sline) pos = next_unfiltered(pos); sindex = sindex_from_sline(sline); + if (!full_screen && !(quit_if_one_screen && one_screen)) + { + /* If not full screen, can't rely on scrolling logic below, since + * "scrolling" may just print lines in the unused part of the screen. */ + pos_clear(); + lclear(); + } + if ((nline = onscreen(pos)) >= 0) { /* diff --git a/less-osc8-open.sh b/less-osc8-open.sh new file mode 100755 index 000000000000..fbcde90a9824 --- /dev/null +++ b/less-osc8-open.sh @@ -0,0 +1,64 @@ +#!/bin/sh + +# Less OSC 8 handler. + +echo() { printf %s\\n "$*"; } + +# Open a link of the form "file://HOST/PATH" or "file:///PATH" +open_file() { + case $1 in + file:///* | file://localhost/*) + less -- "/${1#file://*/}" + ;; + + file://*/*) + linkhost=${1#file://}; linkhost=${linkhost%%/*} + localhost=${HOSTNAME:-$(bash -c 'printf %s "$HOSTNAME"' || uname -n)} 2>/dev/null + + case $localhost in + */* | '') + echo "unable to detect local hostname: $localhost" + exit 1 + ;; + "$linkhost") + less -- "/${1#file://*/}" + ;; + *) + echo "cannot open remote file: $1" + exit 1 + ;; + esac + ;; + + *) + echo "invalid file link: $1" + exit 1 + ;; + esac +} + +# Open a link of the form "man:NAME" or "man:NAME(SECTION)". +open_man() { + case $1 in + man:?*\(*\) ) + sect=${1#*\(}; sect=${sect%?} + name=${1#man:}; name=${name%%\(*} + man -- ${sect:+"$sect"} "$name" + ;; + + man:?*) + man -- "${1#man:}" + ;; + + *) + echo "invalid man link: $1" + exit 1 + ;; + esac +} + +case $1 in +file:*) open_file "$1" ;; +man:*) open_man "$1" ;; +*) echo "unsupported link type: $1"; exit 1 ;; +esac @@ -338,6 +338,12 @@ struct wchar_range_table unsigned int count; }; +struct csl_bitmap_def +{ + constant char *bit_name; + int bit_value; +}; + #if HAVE_POLL typedef short POLL_EVENTS; #endif @@ -440,8 +446,7 @@ typedef enum osc8_state { #define AT_PLACEHOLDER (1 << 7) /* Placeholder for half of double-wide char */ #define AT_COLOR_SHIFT 8 -#define AT_NUM_COLORS 16 -#define AT_COLOR ((AT_NUM_COLORS-1) << AT_COLOR_SHIFT) +#define AT_COLOR ((~(unsigned)0) << AT_COLOR_SHIFT) #define AT_COLOR_ATTN (1 << AT_COLOR_SHIFT) #define AT_COLOR_BIN (2 << AT_COLOR_SHIFT) #define AT_COLOR_CTRL (3 << AT_COLOR_SHIFT) @@ -452,8 +457,12 @@ typedef enum osc8_state { #define AT_COLOR_RSCROLL (8 << AT_COLOR_SHIFT) #define AT_COLOR_HEADER (9 << AT_COLOR_SHIFT) #define AT_COLOR_SEARCH (10 << AT_COLOR_SHIFT) -#define AT_COLOR_SUBSEARCH(i) ((10+(i)) << AT_COLOR_SHIFT) -#define NUM_SEARCH_COLORS (AT_NUM_COLORS-10-1) +#define AT_COLOR_TILDE (11 << AT_COLOR_SHIFT) +#define AT_COLOR_TARGET (12 << AT_COLOR_SHIFT) +#define AT_COLOR_SS_OFFSET 13 /* largest AT_COLOR_* value + 1 */ +#define NUM_SEARCH_COLORS 5 +#define AT_NUM_COLORS (AT_COLOR_SS_OFFSET + NUM_SEARCH_COLORS) +#define AT_COLOR_SUBSEARCH(i) ((AT_COLOR_SS_OFFSET+(i)-1) << AT_COLOR_SHIFT) typedef enum { CT_NULL, CT_4BIT, CT_6BIT } COLOR_TYPE; @@ -629,14 +638,25 @@ typedef enum { #endif /* X11 mouse reporting definitions */ -#define X11MOUSE_BUTTON1 0 /* Left button press */ -#define X11MOUSE_BUTTON2 1 /* Middle button press */ -#define X11MOUSE_BUTTON3 2 /* Right button press */ -#define X11MOUSE_BUTTON_REL 3 /* Button release */ -#define X11MOUSE_DRAG 0x20 /* Drag with button down */ -#define X11MOUSE_WHEEL_UP 0x40 /* Wheel scroll up */ -#define X11MOUSE_WHEEL_DOWN 0x41 /* Wheel scroll down */ -#define X11MOUSE_OFFSET 0x20 /* Added to button & pos bytes to create a char */ +#define X11MOUSE_BUTTON1 0 /* Left button press */ +#define X11MOUSE_BUTTON2 1 /* Middle button press */ +#define X11MOUSE_BUTTON3 2 /* Right button press */ +#define X11MOUSE_BUTTON_REL 3 /* Button release */ +#define X11MOUSE_DRAG 0x20 /* Drag with button down */ +#define X11MOUSE_WHEEL_UP 0x40 /* Wheel scroll up */ +#define X11MOUSE_WHEEL_DOWN 0x41 /* Wheel scroll down */ +#define X11MOUSE_WHEEL_LEFT 0x42 /* Wheel scroll left */ +#define X11MOUSE_WHEEL_RIGHT 0x43 /* Wheel scroll right */ +#define X11MOUSE_OFFSET 0x20 /* Added to button & pos bytes to create a char */ + +/* Mouse features */ +#define EMOUSE_HSCROLL (1<<0) /* Horizontal scroll */ +#define EMOUSE_VSCROLL (1<<1) /* Vertical scroll */ +#define EMOUSE_HDRAG (1<<2) /* Horizontal drag */ +#define EMOUSE_VDRAG (1<<3) /* Vertical drag */ +#define EMOUSE_LCLICK (1<<4) /* Left click */ +#define EMOUSE_RCLICK (1<<5) /* Right click */ +#define EMOUSE_COUNT 6 /* Security features. */ #define SF_EDIT (1<<1) /* Edit file (v) */ @@ -52,7 +52,7 @@ ESC-U Clear search highlighting. &_p_a_t_t_e_r_n * Display only matching lines. --------------------------------------------------- - Search is case-sensitive unless changed with -i or -I. + Search is case-sensitive unless changed with -i or -I. A search pattern may begin with one or more of: ^N or ! Search for NON-matching lines. ^E or * Search multiple files (pass thru END OF FILE). @@ -81,11 +81,11 @@ Each "find open bracket" command goes backward to the open bracket matching the (_N-th) close bracket in the bottom line. - m_<_l_e_t_t_e_r_> Mark the current top line with <letter>. - M_<_l_e_t_t_e_r_> Mark the current bottom line with <letter>. - '_<_l_e_t_t_e_r_> Go to a previously marked position. - '' Go to the previous position. - ^X^X Same as '. + m_<_l_e_t_t_e_r_> * Mark the top line (or line _N) with <letter>. + M_<_l_e_t_t_e_r_> * Mark the bottom line (or line _N) with <letter>. + '_<_l_e_t_t_e_r_> * Go to a previously marked position (put on position _N). + '' * Go to the previous position. + ^X^X * Same as '. ESC-m_<_l_e_t_t_e_r_> Clear a mark. --------------------------------------------------- A mark is any upper-case or lower-case letter. @@ -202,9 +202,9 @@ -V ........ --version Display the version number of "less". -w ........ --hilite-unread - Highlight first new line after forward-screen. + Highlight first new line after full screen movement. -W ........ --HILITE-UNREAD - Highlight first new line after any forward movement. + Highlight first new line after any movement. -x [_N[,...]] --tabs=[_N[,...]] Set tab stops. -X ........ --no-init @@ -222,6 +222,10 @@ --autosave=[_m_/_!_*] Actions which cause the history file to be saved. + --emouse=[_v_s_c_r_o_l_l,_v_d_r_a_g,_h_s_c_r_o_l_l,_h_d_r_a_g,_l_c_l_i_c_k,_r_c_l_i_c_k] + Enable mouse features. + --end-prompt=[_s_t_r_i_n_g] + String to be printed after erasing the prompt. --exit-follow-on-close Exit F command on a pipe when writer closes pipe. --file-size @@ -232,6 +236,8 @@ Stop scrolling when a form feed character is reached. --header=[_L[,_C[,_N]]] Use _L lines (starting at line _N) and _C columns as headers. + --hilite-target + Highlight the target line. --incsearch Search file as each pattern character is typed in. --intr=[_C] @@ -247,7 +253,7 @@ --modelines=[_N] Read _N lines from the input file and look for vim modelines. --mouse - Enable mouse input. + Enable mouse clicking and vertical scrolling. --no-edit-warn Don't warn when using v command on a file opened via LESSOPEN. --no-keypad @@ -276,6 +282,8 @@ Set default options for every search. --show-preproc-errors Display a message if preprocessor exits with an error status. + --past-eof + Scrolling commands continue past end of file. --proc-backspace Process backspaces for bold/underline. --PROC-BACKSPACE @@ -202,86 +202,93 @@ the > in the bottom displayed line. m Followed by any lowercase or uppercase letter, marks the first - displayed line with that letter. If the status column is en‐ - abled via the [1m-J [22moption, the status column shows the marked - line. + displayed line with that letter. If a number N is given, line + number N is marked instead. If the status column is enabled via + the [1m-J [22moption, the status column shows the marked line. - M Acts like m, except the last displayed line is marked rather - than the first displayed line. + M Acts like m, except the last displayed line is marked rather + than the first displayed line. If a number N is given, line + number N is marked instead. ' (Single quote.) Followed by any lowercase or uppercase letter, returns to the position which was previously marked with that letter. Followed by another single quote, returns to the posi‐ tion at which the last "large" movement command was executed. Followed by a ^ or $, jumps to the beginning or end of the file - respectively. Marks are preserved when a new file is examined - within a single invocation of [1mless[22m, so the ' command can be used - to switch between input files. The [1m--save-marks [22moption causes - marks to be preserved across different invocations of [1mless[22m. + respectively. If a number N is given, the marked line is placed + on the N‐th line on the screen. Otherwise, it is placed on the + same line that it was on when it was marked (the first line on + the screen if marked via the [1mm [22mcommand, the last line on the + screen if marked via the [1mM [22mcommand, or the line that was clicked + if marked via the mouse). Marks are preserved when a new file + is examined within a single invocation of [1mless[22m, so the ' command + can be used to switch between input files. The [1m--save-marks [22mop‐ + tion causes marks to be preserved across different invocations + of [1mless[22m. ^X^X Same as single quote. - ESC‐m Followed by any lowercase or uppercase letter, clears the mark + ESC‐m Followed by any lowercase or uppercase letter, clears the mark identified by that letter. - /pattern + /[4mpattern[0m Search forward in the file for the N‐th line containing the pat‐ tern. N defaults to 1. The pattern is a regular expression, as - recognized by the regular expression library supplied by your - system. By default, searching is case‐sensitive (uppercase and - lowercase are considered different); the [1m-i [22moption can be used - to change this. The search starts at the first line displayed + recognized by the regular expression library supplied by your + system. By default, searching is case‐sensitive (uppercase and + lowercase are considered different); the [1m-i [22moption can be used + to change this. The search starts at the first line displayed (but see the [1m-a [22mand [1m-j [22moptions, which change this). - Certain characters are special if entered at the beginning of - the pattern; they modify the type of search rather than become + Certain characters are special if entered at the beginning of + the pattern; they modify the type of search rather than become part of the pattern: ^N or ! Search for lines which do NOT match the pattern. ^E or * - Search multiple files. That is, if the search reaches - the END of the current file without finding a match, the - search continues in the next file in the command line + Search multiple files. That is, if the search reaches + the END of the current file without finding a match, the + search continues in the next file in the command line list. ^F or @ - Begin the search at the first line of the FIRST file in - the command line list, regardless of what is currently - displayed on the screen or the settings of the [1m-a [22mor [1m-j[0m + Begin the search at the first line of the FIRST file in + the command line list, regardless of what is currently + displayed on the screen or the settings of the [1m-a [22mor [1m-j[0m options. - ^K Highlight any text which matches the pattern on the cur‐ + ^K Highlight any text which matches the pattern on the cur‐ rent screen, but don’t move to the first match (KEEP cur‐ rent position). - ^R Don’t interpret regular expression metacharacters; that + ^R Don’t interpret regular expression metacharacters; that is, do a simple textual comparison. - ^S Followed by a digit N between 1 and 5. Only text which + ^S Followed by a digit N between 1 and 5. Only text which has a non‐empty match for the N‐th parenthesized SUB‐PAT‐ - TERN will be considered to match the pattern. For exam‐ - ple, searching for "(abc)|(def)" modified with ^S1 would - search for instances of "abc", but would highlight in‐ + TERN will be considered to match the pattern. For exam‐ + ple, searching for "(abc)|(def)" modified with ^S1 would + search for instances of "abc", but would highlight in‐ stances of both "abc" and "def". (Supported only if [1mless[0m - is built with one of the regular expression libraries - [1mposix[22m, [1mpcre[22m, or [1mpcre2[22m.) Multiple ^S modifiers can be + is built with one of the regular expression libraries + [1mposix[22m, [1mpcre[22m, or [1mpcre2[22m.) Multiple ^S modifiers can be specified, to match more than one sub‐pattern. - ^W WRAP around the current file. That is, if the search - reaches the end of the current file without finding a - match, the search continues from the first line of the - current file up to the line where it started. If the ^W + ^W WRAP around the current file. That is, if the search + reaches the end of the current file without finding a + match, the search continues from the first line of the + current file up to the line where it started. If the ^W modifier is set, the ^E modifier is ignored. - ^L The next character is taken literally; that is, it be‐ - comes part of the pattern even if it is one of the above + ^L The next character is taken literally; that is, it be‐ + comes part of the pattern even if it is one of the above search modifier characters. - ?pattern - Search backward in the file for the N‐th line containing the - pattern. The search starts at the last line displayed (but see + ?[4mpattern[0m + Search backward in the file for the N‐th line containing the + pattern. The search starts at the last line displayed (but see the [1m-a [22mand [1m-j [22moptions, which change this). Certain characters are special as in the / command: @@ -290,15 +297,15 @@ Search for lines which do NOT match the pattern. ^E or * - Search multiple files. That is, if the search reaches - the beginning of the current file without finding a - match, the search continues in the previous file in the + Search multiple files. That is, if the search reaches + the beginning of the current file without finding a + match, the search continues in the previous file in the command line list. ^F or @ Begin the search at the last line of the last file in the - command line list, regardless of what is currently dis‐ - played on the screen or the settings of the [1m-a [22mor [1m-j [22mop‐ + command line list, regardless of what is currently dis‐ + played on the screen or the settings of the [1m-a [22mor [1m-j [22mop‐ tions. ^K As in forward searches. @@ -307,42 +314,43 @@ ^S As in forward searches. - ^W WRAP around the current file. That is, if the search + ^W WRAP around the current file. That is, if the search reaches the beginning of the current file without finding - a match, the search continues from the last line of the + a match, the search continues from the last line of the current file up to the line where it started. ^L As in forward searches. - ESC‐/pattern + ESC‐/[4mpattern[0m Same as "/*". - ESC‐?pattern + ESC‐?[4mpattern[0m Same as "?*". - n Repeat previous search, for N‐th line containing the last pat‐ - tern. If the previous search was modified by ^N, the search is - made for the N‐th line NOT containing the pattern. If the pre‐ - vious search was modified by ^E, the search continues in the - next (or previous) file if not satisfied in the current file. - If the previous search was modified by ^R, the search is done - without using regular expressions. If the previous search was - modified by ^W, the search wraps at the end (or beginning) of - the file. There is no effect if the previous search was modi‐ + n Repeat previous search, for N‐th line containing the last pat‐ + tern. If the previous search was modified by ^N, the search is + made for the N‐th line NOT containing the pattern. If the pre‐ + vious search was modified by ^E, the search continues in the + next (or previous) file if not satisfied in the current file. + If the previous search was modified by ^R, the search is done + without using regular expressions. If the previous search was + modified by ^W, the search wraps at the end (or beginning) of + the file. There is no effect if the previous search was modi‐ fied by ^F or ^K. N Repeat previous search, but in the reverse direction. - ESC‐n Repeat previous search, but crossing file boundaries. The ef‐ + ESC‐n Repeat previous search, but crossing file boundaries. The ef‐ fect is as if the previous search were modified by *. - ESC‐N Repeat previous search, but in the reverse direction and cross‐ + ESC‐N Repeat previous search, but in the reverse direction and cross‐ ing file boundaries. - ESC‐u Undo search highlighting. Turn off highlighting of strings + ESC‐u Undo search highlighting. Turn off highlighting of strings matching the current search pattern. If highlighting is already - off because of a previous ESC‐u command, turn highlighting back - on. Any search command will also turn highlighting back on. + off because of a previous ESC‐u command, turn highlighting back + on. Any search command will also turn highlighting back on. + Also unselects any OSC 8 hyperlink that is currently selected. (Highlighting can also be disabled by toggling the [1m-G [22moption; in that case search commands do not turn highlighting back on.) @@ -350,40 +358,41 @@ status column is enabled via the [1m-J [22moption, this clears all search matches marked in the status column. - &pattern + &[4mpattern[0m Display only lines which match the pattern; lines which do not - match the pattern are not displayed. If pattern is empty (if - you type & immediately followed by ENTER), any filtering is - turned off, and all lines are displayed. While filtering is in - effect, an ampersand is displayed at the beginning of the - prompt, as a reminder that some lines in the file may be hidden. - Multiple & commands may be entered, in which case only lines - which match all of the patterns will be displayed. + match the pattern are hidden. If pattern is empty (if you type + & immediately followed by ENTER), any filtering is turned off, + and all lines are displayed. While filtering is in effect, an + ampersand is displayed at the beginning of the prompt, as a re‐ + minder that some lines in the file may be hidden. Multiple & + commands may be entered, in which case only lines which match + all of the patterns will be displayed. Certain characters are special as in the / command: ^N or ! Display only lines which do NOT match the pattern. - ^R Don’t interpret regular expression metacharacters; that + ^R Don’t interpret regular expression metacharacters; that is, do a simple textual comparison. - :e [filename] - Examine a new file. If the filename is missing, the "current" - file (see the :n and :p commands below) from the list of files - in the command line is re‐examined. A percent sign (%) in the - filename is replaced by the name of the current file. A pound - sign (#) is replaced by the name of the previously examined - file. However, two consecutive percent signs are simply re‐ - placed with a single percent sign. This allows you to enter a - filename that contains a percent sign in the name. Similarly, - two consecutive pound signs are replaced with a single pound - sign. The filename is inserted into the command line list of - files so that it can be seen by subsequent :n and :p commands. - If the filename consists of several files, they are all inserted - into the list of files and the first one is examined. If the - filename contains one or more spaces, the entire filename should - be enclosed in double quotes (also see the [1m-" [22moption). + :e [[4mfilename[24m] + Examine a new file. If the filename is missing, the "current" + file (see the :n and :p commands below) from the list of files + in the command line is re‐examined. A percent sign (%) in the + filename is replaced by the shell‐escaped name of the current + file. A pound sign (#) is replaced by the shell‐escaped name of + the previously examined file. However, two consecutive percent + signs are simply replaced with a single percent sign. This al‐ + lows you to enter a filename that contains a percent sign in the + name. Similarly, two consecutive pound signs are replaced with + a single pound sign. The filename is inserted into the command + line list of files so that it can be seen by subsequent :n and + :p commands. If the filename consists of several files, they + are all inserted into the list of files and the first one is ex‐ + amined. If the filename contains one or more spaces, the entire + filename should be enclosed in double quotes (also see the [1m-"[0m + option). ^X^V or E Same as :e. Warning: some systems use ^V as a special literal‐ @@ -468,7 +477,7 @@ a long option name rather than a single option letter. You must press ENTER or RETURN after typing the option name. - +cmd Causes the specified cmd to be executed each time a new file is + +[4mcmd[24m Causes the specified cmd to be executed each time a new file is examined. For example, +G causes [1mless [22mto initially display each file starting at the end rather than the beginning. @@ -486,95 +495,89 @@ ther VISUAL nor EDITOR is defined. See also the discussion of LESSEDIT under the section on PROMPTS below. - ! shell‐command + ! [4mshell‐command[0m Invokes a shell to run the shell‐command given. A percent sign - (%) in the command is replaced by the name of the current file. - A pound sign (#) is replaced by the name of the previously exam‐ - ined file. "!!" repeats the last shell command. "!" with no - shell command invokes an interactive shell. If a ^P (CONTROL‐P) - is entered immediately after the !, no "done" message is printed - after the shell command is executed. On Unix systems, the shell - is taken from the environment variable SHELL, or defaults to - "sh". On MS‐DOS, Windows, and OS/2 systems, the shell is the - normal command processor. + (%) in the filename is replaced by the shell‐escaped name of the + current file. A pound sign (#) is replaced by the shell‐escaped + name of the previously examined file. "!!" repeats the last + shell command. "!" with no shell command invokes an interactive + shell. If a ^P (CONTROL‐P) is entered immediately after the !, + no "done" message is printed after the shell command is exe‐ + cuted. On Unix systems, the shell is taken from the environment + variable SHELL, or defaults to "sh". On MS‐DOS, Windows, and + OS/2 systems, the shell is the normal command processor. - # shell‐command + # [4mshell‐command[0m Similar to the "!" command, except that the command is expanded in the same way as prompt strings. For example, the name of the current file would be given as "%f". - | <m> shell‐command + | <[4mm[24m> [4mshell‐command[0m <m> represents any mark letter. Pipes a section of the input - file to the given shell command. The section of the file to be - piped is between the position marked by the letter and the cur‐ - rent screen. The entire current screen is included, regardless - of whether the marked position is before or after the current - screen. <m> may also be ^ or $ to indicate beginning or end of - file respectively. If <m> is . or newline, the current screen - is piped. If a ^P (CONTROL‐P) is entered immediately after the - mark letter, no "done" message is printed after the shell com‐ - mand is executed. + file to the given shell command. If the marked line is before + the top line of the current screen, the section to be piped is + between the marked line and the bottom line of the current + screen, inclusive. Otherwise (if the marked line is the top + line of the current screen or after it) the section of the file + to be piped is between the top line of the current screen and + the marked line, inclusive. <m> may also be ^ or $ to indicate + beginning or end of file respectively. If <m> is . or newline, + the current screen is piped. If a ^P (CONTROL‐P) is entered im‐ + mediately after the mark letter, no "done" message is printed + after the shell command is executed. - s filename - Save the input to a file. This works only if the input is a + s [4mfilename[0m + Save the input to a file. This works only if the input is a pipe, not an ordinary file. ^O^O - Run a shell command to open the URI in the current OSC 8 hyper‐ - link, selected by a previous ^O^N or ^O^P command. To find the - shell command, the environment variable named "LESS_OSC8_xxx" is - read, where "xxx" is the scheme from the URI (the part before - the first colon), or is empty if there is no colon in the URI. - The value of the environment variable is then expanded in the - same way as prompt strings (in particular, any instance of "%o" - is replaced with the URI) to produce an OSC 8 "handler" shell - command. The standard output from the handler is an "opener" - shell command which is then executed to open the URI. - - There are two special cases: + Run a shell command to open the URI in the current OSC 8 hyper‐ + link, selected by a previous ^O^N or ^O^P command. The shell + command is given by the environment variable named + "LESS_OSC8_OPEN_xxx" where "xxx" is the scheme from the URI (the + part before the first colon), converted to lowercase. If there + is no colon in the URI, the environment variable + LESS_OSC8_OPEN_NONE is used. The URI from the hyperlink is then + shell‐escaped and appended to the value of the environment vari‐ + able after a space, and the resulting string is executed as a + shell command. - 1. If the URI begins with "#", the remainder of the - URI is taken to be the value of the id parameter - in another OSC 8 link in the same file, and ^O^O - will simply jump to that link. + For example, if you wish to open https links by invoking a pro‐ + gram called "mybrowser" with a "--new-window" option, you could + set - 2. If the opener begins with the characters ":e" fol‐ - lowed by whitespace and a filename, then instead - of running the opener as a shell command, the - specified filename is opened in the current in‐ - stance of [1mless[22m. + LESS_OSC8_OPEN_https="mybrowser --new-window" - In a simple case where the opener accepts the complete URI as a - command line parameter, the handler may be as simple as + If the handler command begins with "-", the command is not dis‐ + played before it is executed. If the handler command begins + with ^P (CONTROL‐P), the "link done" message is not displayed + after it is executed. If the handler command begins with ^P + followed by "-", neither the command nor the "link done" message + is displayed. - echo mybrowser '%o' + If you attempt to open a link with the "xxx" scheme and the + LESS_OSC8_OPEN_xxx variable is not set, the variable + LESS_OSC8_OPEN_ANY is tried. If neither LESS_OSC8_OPEN_xxx nor + LESS_OSC8_OPEN_ANY is set, links using the "xxx" scheme cannot + be opened. However, there is a default value for + LESS_OSC8_OPEN_ANY which invokes the program [1mless-osc8-open[22m(1). + This program will open links with the schemes "man" (by running + [1mman[22m(1)) or "file" (by running another instance of [1mless[22m(1) if the + file is local). [1mless-osc8-open [22mshould work on systems which + provide a POSIX‐compatible shell. - In other cases, the URI may need to be modified, so the handler - may have to do some manipulation of the %o value. + Any shell metacharacters such as semicolons, dollar signs, am‐ + persands, etc. in the URI will be shell‐escaped before the URI + is appended to the handler command. If the handler passes the + URI or any substring of it to a shell, it should take care to + appropriately quote such strings, to prevent execution of unin‐ + tended shell commands when opening a URI which contains shell + metacharacters. - If the LESS_OSC8_xxx variable is not set, the variable - LESS_OSC8_ANY is tried. If neither LESS_OSC8_xxx nor - LESS_OSC8_ANY is set, links using the "xxx" scheme cannot be - opened. However, there are default handlers for the schemes - "man" (used when LESS_OSC8_man is not set) and "file" (used when - LESS_OSC8_file is not set), which should work on systems which - provide the [1msed[22m(1) command and a shell with syntax compatible - with the Bourne shell [1msh[22m(1). If you use LESS_OSC8_ANY to over‐ - ride LESS_OSC8_file, you must set LESS_OSC8_file to "-" to indi‐ - cate that the default value should not be used, and likewise for - LESS_OSC8_man. - - The URI passed to an OSC8 handler via %o is guaranteed not to - contain any single quote or double quote characters, but it may - contain any other shell metacharacters such as semicolons, dol‐ - lar signs, ampersands, etc. The handler should take care to ap‐ - propriately quote parameters in the opener command, to prevent - execution of unintended shell commands in the case of opening a - URI which contains shell metacharacters. Also, since the han‐ - dler command is expanded like a command prompt, any metacharac‐ - ters interpreted by prompt expansion (such as percent, dot, - colon, backslash, etc.) must be escaped with a backslash (see - the PROMPTS section for details). + As a special case, if the URI begins with "#", the remainder of + the URI is taken to be the value of the id parameter in another + OSC 8 link in the same file, and ^O^O will simply jump to that + link rather than running a handler program. ^X When the "Waiting for data" message is displayed, such as while in the F command, pressing ^X will stop [1mless [22mfrom waiting and @@ -649,7 +652,7 @@ of the screen, thus skipping all lines displayed on the screen. [1m-A [22mor [1m--SEARCH-SKIP-SCREEN[0m - Causes all forward searches (not just non‐repeated searches) to + auses all forward searches (not just non‐repeated searches) to start just after the target line, and all backward searches to start just before the target line. Thus, forward searches will skip part of the displayed screen (from the first line up to and @@ -707,6 +710,8 @@ H Header lines and columns, set via the [1m--header [22moption. + J Target line when highlighted via --hilite-target. + M Mark letters in the status column. N Line numbers enabled via the [1m-N [22moption. @@ -717,9 +722,12 @@ S Search results. + T The tilde lines displayed after the end of the file or + before the beginning of the file. + W The highlight enabled via the [1m-w [22moption. - 1-5 The text in a search result which matches the first + 1-5 The text in a search result which matches the first through fifth parenthesized sub‐pattern. Sub‐pattern coloring works only if [1mless [22mis built with one of the reg‐ ular expression libraries [1mposix[22m, [1mpcre[22m, or [1mpcre2[22m. @@ -732,30 +740,30 @@ u Underlined text. - The uppercase letters and digits can be used only when the - [1m--use-color [22moption is enabled. When text color is specified by - both an uppercase letter and a lowercase letter, the uppercase - letter takes precedence. For example, error messages are nor‐ - mally displayed as standout text. So if both "s" and "E" are - given a color, the "E" color applies to error messages, and the + The uppercase letters and digits can be used only when the + [1m--use-color [22moption is enabled. When text color is specified by + both an uppercase letter and a lowercase letter, the uppercase + letter takes precedence. For example, error messages are nor‐ + mally displayed as standout text. So if both "s" and "E" are + given a color, the "E" color applies to error messages, and the "s" color applies to other standout text. The lowercase letters - refer to bold and underline text formed by overstriking with - backspaces (see the [1m-U [22moption) and to non‐content text (such as - line numbers and prompts), but not to text formatted using ANSI - escape sequences with the [1m-R [22moption (but see the note below for + refer to bold and underline text formed by overstriking with + backspaces (see the [1m-U [22moption) and to non‐content text (such as + line numbers and prompts), but not to text formatted using ANSI + escape sequences with the [1m-R [22moption (but see the note below for different behavior on Windows and MS‐DOS). - A lowercase letter may be followed by a + to indicate that the - normal format change and the specified color should both be + A lowercase letter may be followed by a + to indicate that the + normal format change and the specified color should both be used. For example, [1m-Dug [22mdisplays underlined text as green with‐ - out underlining; the green color has replaced the usual under‐ - line formatting. But [1m-Du+g [22mdisplays underlined text as both + out underlining; the green color has replaced the usual under‐ + line formatting. But [1m-Du+g [22mdisplays underlined text as both green and in underlined format. [4mcolor[24m is either a 4‐bit color string or an 8‐bit color string: - A 4‐bit color string is one or two characters, where the first - character specifies the foreground color and the second speci‐ + A 4‐bit color string is one or two characters, where the first + character specifies the foreground color and the second speci‐ fies the background color as follows: b Blue @@ -774,26 +782,26 @@ y Yellow - The corresponding uppercase letter denotes a brighter shade of - the color. For example, [1m-DNGk [22mdisplays line numbers as bright - green text on a black background, and [1m-DEbR [22mdisplays error mes‐ - sages as blue text on a bright red background. If either char‐ - acter is a "-" or is omitted, the corresponding color is set to + The corresponding uppercase letter denotes a brighter shade of + the color. For example, [1m-DNGk [22mdisplays line numbers as bright + green text on a black background, and [1m-DEbR [22mdisplays error mes‐ + sages as blue text on a bright red background. If either char‐ + acter is a "-" or is omitted, the corresponding color is set to that of normal text. - An 8‐bit color string is one or two decimal integers separated + An 8‐bit color string is one or two decimal integers separated by a dot, where the first integer specifies the foreground color - and the second specifies the background color. Each integer is - a value between 0 and 255 inclusive which selects a "CSI 38;5" - color value (see https://en.wikipedia.org/wiki/ANSI_escape_code - #SGR). If either integer is a "-" or is omitted, the corre‐ + and the second specifies the background color. Each integer is + a value between 0 and 255 inclusive which selects a "CSI 38;5" + color value (see https://en.wikipedia.org/wiki/ANSI_escape_code + #SGR). If either integer is a "-" or is omitted, the corre‐ sponding color is set to that of normal text. - A 4‐bit or 8‐bit color string may be followed by one or more of - the following characters to set text attributes in addition to + A 4‐bit or 8‐bit color string may be followed by one or more of + the following characters to set text attributes in addition to the color. - s or ˜ Standout (reverse video) + s or ~ Standout (reverse video) u or _ Underline @@ -801,48 +809,48 @@ l or & Blinking - On MS‐DOS and Windows, the [1m--color [22moption behaves differently + On MS‐DOS and Windows, the [1m--color [22moption behaves differently from what is described above in these ways: • The bold (d and *) and blinking (l and &) text attributes at the end of a color string are not supported. - • Lowercase color selector letters refer to text formatted - by ANSI escape sequences with [1m-R[22m, in addition to over‐ + • Lowercase color selector letters refer to text formatted + by ANSI escape sequences with [1m-R[22m, in addition to over‐ struck and non‐content text (but see [1m-Da[22m). - • For historical reasons, when a lowercase color selector - letter is followed by a numeric color value, the number - is not interpreted as an "CSI 38;5" color value as de‐ - scribed above, but instead as a 4‐bit - CHAR_INFO.Attributes value, between 0 and 15 inclusive + • For historical reasons, when a lowercase color selector + letter is followed by a numeric color value, the number + is not interpreted as an "CSI 38;5" color value as de‐ + scribed above, but instead as a 4‐bit + CHAR_INFO.Attributes value, between 0 and 15 inclusive (see https://learn.microsoft.com/en-us/windows/console/ char-info-str). To avoid confusion, it is recommended that the equivalent - letters rather than numbers be used after a lowercase + letters rather than numbers be used after a lowercase color selector on MS‐DOS/Windows. - • Numeric color values ("CSI 38;5" color) following an up‐ - percase color selector letter are not supported on sys‐ + • Numeric color values ("CSI 38;5" color) following an up‐ + percase color selector letter are not supported on sys‐ tems earlier than Windows 10. - • Only a limited set of ANSI escape sequences to set color - in the content work correctly. 4‐bit color sequences + • Only a limited set of ANSI escape sequences to set color + in the content work correctly. 4‐bit color sequences work, but "CSI 38;5" color sequences do not. • The [1m-Da [22moption makes the behavior of [1m--color [22mmore similar to its behavior on non‐MS‐DOS/Windows systems by (1) mak‐ ing lowercase color selector letters not affect text for‐ - matted with ANSI escape sequences, and (2) allowing "CSI + matted with ANSI escape sequences, and (2) allowing "CSI 38;5" color sequences in the content work by passing them to the terminal (only on Windows 10 and later; on earlier Windows systems, such sequences do not work regardless of the setting of [1m-Da[22m). [1m-e [22mor [1m--quit-at-eof[0m - Causes [1mless [22mto automatically exit the second time it reaches - end‐of‐file. By default, the only way to exit [1mless [22mis via the + Causes [1mless [22mto automatically exit the second time it reaches + end‐of‐file. By default, the only way to exit [1mless [22mis via the "q" command. [1m-E [22mor [1m--QUIT-AT-EOF[0m @@ -851,141 +859,141 @@ [1m-f [22mor [1m--force[0m Forces non‐regular files to be opened. (A non‐regular file is a - directory or a device special file.) Also suppresses the warn‐ + directory or a device special file.) Also suppresses the warn‐ ing message when a binary file is opened. By default, [1mless [22mwill refuse to open non‐regular files. Note that some operating sys‐ tems will not allow directories to be read, even if [1m-f [22mis set. [1m-F [22mor [1m--quit-if-one-screen[0m Causes [1mless [22mto automatically exit if the entire file can be dis‐ - played on the first screen. Also see the description of the + played on the first screen. Also see the description of the LESS_SHELL_LINES environment variable below. [1m-g [22mor [1m--hilite-search[0m - Normally, [1mless [22mwill highlight ALL strings which match the last - search command. The [1m-g [22moption changes this behavior to high‐ - light only the particular string which was found by the last + Normally, [1mless [22mwill highlight ALL strings which match the last + search command. The [1m-g [22moption changes this behavior to high‐ + light only the particular string which was found by the last search command. This can cause [1mless [22mto run somewhat faster than the default. [1m-G [22mor [1m--HILITE-SEARCH[0m - The -G option suppresses all highlighting of strings found by + The -G option suppresses all highlighting of strings found by search commands. [1m-h[4m[22mn[24m or [1m--max-back-scroll=[4m[22mn[0m - Specifies a maximum number of lines to scroll backward. If it + Specifies a maximum number of lines to scroll backward. If it is necessary to scroll backward more than [4mn[24m lines, the screen is repainted in a forward direction instead. (If the terminal does not have the ability to scroll backward, [1m-h0 [22mis implied.) [1m-i [22mor [1m--ignore-case[0m Causes searches to ignore case; that is, uppercase and lowercase - are considered identical. This option is ignored if any upper‐ - case letters appear in the search pattern; in other words, if a - pattern contains uppercase letters, then that search does not + are considered identical. This option is ignored if any upper‐ + case letters appear in the search pattern; in other words, if a + pattern contains uppercase letters, then that search does not ignore case. [1m-I [22mor [1m--IGNORE-CASE[0m - Like [1m-i[22m, but searches ignore case even if the pattern contains + Like [1m-i[22m, but searches ignore case even if the pattern contains uppercase letters. [1m-j[4m[22mn[24m or [1m--jump-target=[4m[22mn[0m - Specifies a line on the screen where the "target" line is to be - positioned. The target line is the line specified by any com‐ - mand to search for a pattern, jump to a line number, jump to a + Specifies a line on the screen where the "target" line is to be + positioned. The target line is the line specified by any com‐ + mand to search for a pattern, jump to a line number, jump to a file percentage or jump to a tag. The screen line may be speci‐ - fied by a number: the top line on the screen is 1, the next is + fied by a number: the top line on the screen is 1, the next is 2, and so on. The number may be negative to specify a line rel‐ ative to the bottom of the screen: the bottom line on the screen - is -1, the second to the bottom is -2, and so on. Alternately, - the screen line may be specified as a fraction of the height of - the screen, starting with a decimal point: .5 is in the middle - of the screen, .3 is three tenths down from the first line, and - so on. If the line is specified as a fraction, the actual line - number is recalculated if the terminal window is resized. If - the [1m--header [22moption is used and the target line specified by [1m-j[0m + is -1, the second to the bottom is -2, and so on. Alternately, + the screen line may be specified as a fraction of the height of + the screen, starting with a decimal point: .5 is in the middle + of the screen, .3 is three tenths down from the first line, and + so on. If the line is specified as a fraction, the actual line + number is recalculated if the terminal window is resized. If + the [1m--header [22moption is used and the target line specified by [1m-j[0m would be obscured by the header, the target line is moved to the first line after the header. - If any form of the [1m-j [22moption is used, repeated forward searches - (invoked with "n" or "N") begin at the line immediately after - the target line, and repeated backward searches begin at the - target line, unless changed by [1m-a [22mor [1m-A[22m. For example, if "[1m-j4[22m" - is used, the target line is the fourth line on the screen, so + If any form of the [1m-j [22moption is used, repeated forward searches + (invoked with "n" or "N") begin at the line immediately after + the target line, and repeated backward searches begin at the + target line, unless changed by [1m-a [22mor [1m-A[22m. For example, if "[1m-j4[22m" + is used, the target line is the fourth line on the screen, so forward searches begin at the fifth line on the screen. However - nonrepeated searches (invoked with "/" or "?") always begin at + nonrepeated searches (invoked with "/" or "?") always begin at the first or last line on the screen respectively. [1m-J [22mor [1m--status-column[0m - Displays a status column at the left edge of the screen. The + Displays a status column at the left edge of the screen. The character displayed in the status column may be one of: > The line is chopped with the [1m-S [22moption, and the text that - is chopped off beyond the right edge of the screen con‐ + is chopped off beyond the right edge of the screen con‐ tains a match for the current search. - < The line is horizontally shifted, and the text that is - shifted beyond the left side of the screen contains a + < The line is horizontally shifted, and the text that is + shifted beyond the left side of the screen contains a match for the current search. - = The line is both chopped and shifted, and there are + = The line is both chopped and shifted, and there are matches beyond both sides of the screen. - * There are matches in the visible part of the line but + * There are matches in the visible part of the line but none to the right or left of it. a‐z, A‐Z - The line has been marked with the corresponding letter + The line has been marked with the corresponding letter via the m or M command. - # The line has been marked by left‐clicking it with the + # The line has been marked by left‐clicking it with the mouse when the [1m--mouse [22moption is in effect. [1m-k[4m[22mfilename[24m or [1m--lesskey-file=[4m[22mfilename[0m Causes [1mless [22mto open and interpret the named file as a [1mlesskey[22m(1) - binary file. Multiple [1m-k [22moptions may be specified. If the - LESSKEY or LESSKEY_SYSTEM environment variable is set, or if a + binary file. Multiple [1m-k [22moptions may be specified. If the + LESSKEY or LESSKEY_SYSTEM environment variable is set, or if a lesskey file is found in a standard place (see KEY BINDINGS), it - is also used as a [1mlesskey [22mfile. Note the warning under + is also used as a [1mlesskey [22mfile. Note the warning under [1m--lesskey-content [22mbelow. [1m--lesskey-src=[4m[22mfilename[0m Causes [1mless [22mto open and interpret the named file as a [1mlesskey[22m(1) - source file. If the LESSKEYIN or LESSKEYIN_SYSTEM environment + source file. If the LESSKEYIN or LESSKEYIN_SYSTEM environment variable is set, or if a lesskey source file is found in a stan‐ - dard place (see KEY BINDINGS), it is also used as a lesskey - source file. Prior to version 582, the [1mlesskey [22mprogram needed - to be run to convert a lesskey [4msource[24m file to a lesskey [4mbinary[0m - file for [1mless [22mto use. Newer versions of [1mless [22mread the lesskey - source file directly and ignore the binary file if the source + dard place (see KEY BINDINGS), it is also used as a lesskey + source file. Prior to version 582, the [1mlesskey [22mprogram needed + to be run to convert a lesskey [4msource[24m file to a lesskey [4mbinary[0m + file for [1mless [22mto use. Newer versions of [1mless [22mread the lesskey + source file directly and ignore the binary file if the source file exists. Note the warning under [1m--lesskey-content [22mbelow. [1m--lesskey-content=[4m[22mtext[0m Causes [1mless [22mto interpret the specified text as the contents of a [1mlesskey[22m(1) source file. In the text, [1mlesskey [22mlines may be sepa‐ - rated by either newlines as usual, or by semicolons. A literal - semicolon may be represented by a backslash followed by a semi‐ + rated by either newlines as usual, or by semicolons. A literal + semicolon may be represented by a backslash followed by a semi‐ colon. Warning: certain environment variables such as LESS, LESSSECURE, - LESSCHARSET and others, which are used early in startup, cannot - be set in a file specified by a command line option - ([1m--lesskey[22m,[1m--lesskey-src [22mor [1m--lesskey-content[22m). When using a - [1mlesskey [22mfile to set environment variables, it is safer to use - the default lesskey file, or to specify the file using the - LESSKEYIN or LESSKEY_CONTENT environment variables rather than - using a command line option. + LESSCHARSET and others, which are used early in startup, cannot + be set in a file specified by a command line option ([1m--lesskey[22m, + [1m--lesskey-src [22mor [1m--lesskey-content[22m). When using a [1mlesskey [22mfile + to set environment variables, it is safer to use the default + lesskey file, or to specify the file using the LESSKEYIN or + LESSKEY_CONTENT environment variables rather than using a com‐ + mand line option. [1m-K [22mor [1m--quit-on-intr[0m - Causes [1mless [22mto exit immediately (with status 2) when an inter‐ - rupt character (usually ^C) is typed. Normally, an interrupt + Causes [1mless [22mto exit immediately (with status 2) when an inter‐ + rupt character (usually ^C) is typed. Normally, an interrupt character causes [1mless [22mto stop whatever it is doing and return to its command prompt. [1m-L [22mor [1m--no-lessopen[0m - Ignore the LESSOPEN environment variable (see the INPUT PRE‐ - PROCESSOR section below). This option can be set from within - [1mless[22m, but it will apply only to files opened subsequently, not + Ignore the LESSOPEN environment variable (see the INPUT PRE‐ + PROCESSOR section below). This option can be set from within + [1mless[22m, but it will apply only to files opened subsequently, not to the file which is currently open. [1m-m [22mor [1m--long-prompt[0m @@ -996,45 +1004,45 @@ Causes [1mless [22mto prompt even more verbosely than [1mmore[22m(1). [1m-n [22mor [1m--line-numbers[0m - Suppresses line numbers. The default (to use line numbers) may - cause [1mless [22mto run more slowly in some cases, especially with a - very large input file. Using line numbers means: the line num‐ - ber will be displayed in the verbose prompt and in the = com‐ + Suppresses line numbers. The default (to use line numbers) may + cause [1mless [22mto run more slowly in some cases, especially with a + very large input file. Using line numbers means: the line num‐ + ber will be displayed in the verbose prompt and in the = com‐ mand, and the v command will pass the current line number to the editor (see also the discussion of LESSEDIT in PROMPTS below). [1m-N [22mor [1m--LINE-NUMBERS[0m - Causes a line number to be displayed at the beginning of each + Causes a line number to be displayed at the beginning of each line in the display. [1m-o[4m[22mfilename[24m or [1m--log-file=[4m[22mfilename[0m - Causes [1mless [22mto copy its input to the named file as it is being + Causes [1mless [22mto copy its input to the named file as it is being viewed. This applies only when the input file is a pipe, not an - ordinary file. If the file already exists, [1mless [22mwill ask for + ordinary file. If the file already exists, [1mless [22mwill ask for confirmation before overwriting it. [1m-O[4m[22mfilename[24m or [1m--LOG-FILE=[4m[22mfilename[0m The [1m-O [22moption is like [1m-o, [22mbut it will overwrite an existing file without asking for confirmation. - If no log file has been specified, the [1m-o [22mand [1m-O [22moptions can be - used from within [1mless [22mto specify a log file. Without a file + If no log file has been specified, the [1m-o [22mand [1m-O [22moptions can be + used from within [1mless [22mto specify a log file. Without a file name, they will simply report the name of the log file. The "s" command is equivalent to specifying [1m-o [22mfrom within [1mless[22m. [1m-p[4m[22mpattern[24m or [1m--pattern=[4m[22mpattern[0m - The -p option on the command line is equivalent to specifying - +/[4mpattern[24m; that is, it tells [1mless [22mto start at the first occur‐ + The -p option on the command line is equivalent to specifying + +/[4mpattern[24m; that is, it tells [1mless [22mto start at the first occur‐ rence of [4mpattern[24m in the file. [1m-P[4m[22mprompt[24m or [1m--prompt=[4m[22mprompt[0m - Provides a way to tailor the three prompt styles to your own + Provides a way to tailor the three prompt styles to your own preference. This option would normally be put in the LESS envi‐ ronment variable, rather than being typed in with each [1mless [22mcom‐ mand. Such an option must either be the last option in the LESS variable, or be terminated by a dollar sign. - [1m-Ps [22mfollowed by a string changes the default (short) prompt + [1m-Ps [22mfollowed by a string changes the default (short) prompt to that string. [1m-Pm [22mchanges the medium ([1m-m[22m) prompt. @@ -1045,75 +1053,75 @@ [1m-P= [22mchanges the message printed by the = command. - [1m-Pw [22mchanges the message printed while waiting for data (in + [1m-Pw [22mchanges the message printed while waiting for data (in the "F" command). - All prompt strings consist of a sequence of letters and special + All prompt strings consist of a sequence of letters and special escape sequences. See the section on PROMPTS for more details. [1m-q [22mor [1m--quiet [22mor [1m--silent[0m - Causes moderately "quiet" operation: the terminal bell is not + Causes moderately "quiet" operation: the terminal bell is not rung if an attempt is made to scroll past the end of the file or before the beginning of the file. If the terminal has a "visual - bell", it is used instead. The bell will be rung on certain - other errors, such as typing an invalid character. The default + bell", it is used instead. The bell will be rung on certain + other errors, such as typing an invalid character. The default is to ring the terminal bell in all such cases. [1m-Q [22mor [1m--QUIET [22mor [1m--SILENT[0m - Causes totally "quiet" operation: the terminal bell is never - rung. If the terminal has a "visual bell", it is used in all + Causes totally "quiet" operation: the terminal bell is never + rung. If the terminal has a "visual bell", it is used in all cases where the terminal bell would have been rung. [1m-r [22mor [1m--raw-control-chars[0m Causes "raw" control characters to be displayed. The default is - to display control characters using the caret notation; for ex‐ - ample, a control‐A (octal 001) is displayed as "^A" (with some + to display control characters using the caret notation; for ex‐ + ample, a control‐A (octal 001) is displayed as "^A" (with some exceptions as described under the [1m-U [22moption). Warning: when the - [1m-r [22moption is used, [1mless [22mcannot keep track of the actual appear‐ - ance of the screen (since this depends on how the screen re‐ - sponds to each type of control character). Thus, various dis‐ - play problems may result, such as long lines being split in the + [1m-r [22moption is used, [1mless [22mcannot keep track of the actual appear‐ + ance of the screen (since this depends on how the screen re‐ + sponds to each type of control character). Thus, various dis‐ + play problems may result, such as long lines being split in the wrong place. USE OF THE [1m-r [22mOPTION IS DANGEROUS AND IS NOT RECOMMENDED. - The [1m-r [22moption can be set on the command line or via the - com‐ + The [1m-r [22moption can be set on the command line or via the - com‐ mand, but to avoid unintentional use, it cannot be set in a LESS environment variable. If [1m-r [22mappears in a LESS environment vari‐ able, it is treated as if it were [1m-R[22m. [1m-R [22mor [1m--RAW-CONTROL-CHARS[0m - Like [1m-r[22m, but only a limited set of escape sequences are output - in "raw" form. Unlike [1m-r[22m, the screen appearance is maintained + Like [1m-r[22m, but only a limited set of escape sequences are output + in "raw" form. Unlike [1m-r[22m, the screen appearance is maintained correctly. The sequences which are output raw are: 1. ANSI SGR ("color") sequences 2. OSC 8 hyperlinks - 3. Other OSC sequences, if the OSC type number is listed in the + 3. Other OSC sequences, if the OSC type number is listed in the LESSANSIOSCALLOW environment variable 4. OSC sequences starting with a non‐standard introductory char‐ - acter (that is, something other than "]"), if the character is - listed in the LESSANSIOSCCHARS environment variable followed by + acter (that is, something other than "]"), if the character is + listed in the LESSANSIOSCCHARS environment variable followed by an asterisk ANSI color escape sequences are sequences of the form: ESC [ ... m - where the "..." is zero or more color specification characters. - Color escape sequences are only supported when the color is - changed within one line, not across lines. In other words, the - beginning of each line is assumed to be normal (non‐colored), + where the "..." is zero or more color specification characters. + Color escape sequences are only supported when the color is + changed within one line, not across lines. In other words, the + beginning of each line is assumed to be normal (non‐colored), regardless of any escape sequences in previous lines. - You can make [1mless [22mthink that characters other than "m" can end - ANSI color escape sequences by setting the environment variable + You can make [1mless [22mthink that characters other than "m" can end + ANSI color escape sequences by setting the environment variable LESSANSIENDCHARS to the list of characters which can end a color - escape sequence. And you can make [1mless [22mthink that characters - other than the standard ones may appear between the ESC and the - m by setting the environment variable LESSANSIMIDCHARS to the + escape sequence. And you can make [1mless [22mthink that characters + other than the standard ones may appear between the ESC and the + m by setting the environment variable LESSANSIMIDCHARS to the list of characters which can appear. OSC sequences are of the form: @@ -1125,124 +1133,126 @@ two‐character sequence "ESC \". [1m-s [22mor [1m--squeeze-blank-lines[0m - Causes consecutive blank lines to be squeezed into a single + Causes consecutive blank lines to be squeezed into a single blank line. This is useful when viewing [1mnroff[22m(1) output. [1m-S [22mor [1m--chop-long-lines[0m - Causes lines longer than the screen width to be chopped (trun‐ + Causes lines longer than the screen width to be chopped (trun‐ cated) rather than wrapped. That is, the portion of a long line that does not fit in the screen width is not displayed until you - press RIGHT‐ARROW. The default is to wrap long lines; that is, + press RIGHT‐ARROW. The default is to wrap long lines; that is, display the remainder on the next line. See also the [1m--wordwrap[0m - option. While the [1m--header [22moption is active, the [1m-S [22moption is + option. While the [1m--header [22moption is active, the [1m-S [22moption is ignored, and lines longer than the screen width are truncated. [1m-t[4m[22mtag[24m or [1m--tag=[4m[22mtag[0m The [1m-t [22moption, followed immediately by a TAG, will edit the file - containing that tag. For this to work, tag information must be - available; for example, there may be a file in the current di‐ + containing that tag. For this to work, tag information must be + available; for example, there may be a file in the current di‐ rectory called "tags", which was previously built by [1mctags[22m(1) or an equivalent command. If the environment variable LESSGLOBALT‐ - AGS is set, it is taken to be the name of a command compatible - with [1mglobal[22m(1), and that command is executed to find the tag. + AGS is set, it is taken to be the name of a command compatible + with [1mglobal[22m(1), and that command is executed to find the tag. (See http://www.gnu.org/software/global/global.html). The [1m-t[0m - option may also be specified from within [1mless [22m(using the - com‐ - mand) as a way of examining a new file. The command ":t" is + option may also be specified from within [1mless [22m(using the - com‐ + mand) as a way of examining a new file. The command ":t" is equivalent to specifying [1m-t [22mfrom within [1mless[22m. [1m-T[4m[22mtagsfile[24m or [1m--tag-file=[4m[22mtagsfile[0m Specifies a tags file to be used instead of "tags". [1m-u [22mor [1m--underline-special[0m - Causes backspaces and carriage returns to be treated as print‐ - able characters; that is, they are sent to the terminal when + Causes backspaces and carriage returns to be treated as print‐ + able characters; that is, they are sent to the terminal when they appear in the input. [1m-U [22mor [1m--UNDERLINE-SPECIAL[0m - Causes backspaces, tabs, carriage returns and "formatting char‐ + Causes backspaces, tabs, carriage returns and "formatting char‐ acters" (as defined by Unicode) to be treated as control charac‐ ters; that is, they are handled as specified by the [1m-r [22moption. - By default, if neither [1m-u [22mnor [1m-U [22mis given, backspaces which ap‐ - pear adjacent to an underscore character are treated specially: - the underlined text is displayed using the terminal’s hardware - underlining capability. Also, backspaces which appear between - two identical characters are treated specially: the overstruck + By default, if neither [1m-u [22mnor [1m-U [22mis given, backspaces which ap‐ + pear adjacent to an underscore character are treated specially: + the underlined text is displayed using the terminal’s hardware + underlining capability. Also, backspaces which appear between + two identical characters are treated specially: the overstruck text is printed using the terminal’s hardware boldface capabili‐ - ty. Other backspaces are deleted, along with the preceding - character. Carriage returns immediately followed by a newline + ty. Other backspaces are deleted, along with the preceding + character. Carriage returns immediately followed by a newline are deleted. Other carriage returns are handled as specified by - the [1m-r [22moption. Unicode formatting characters, such as the Byte - Order Mark, are sent to the terminal. Text which is overstruck + the [1m-r [22moption. Unicode formatting characters, such as the Byte + Order Mark, are sent to the terminal. Text which is overstruck or underlined can be searched for if neither [1m-u [22mnor [1m-U [22mis in ef‐ fect. - See also the [1m--proc-backspace[22m,[1m--proc-tab[22m, and [1m--proc-return [22mop‐ + See also the [1m--proc-backspace[22m,[1m--proc-tab[22m, and [1m--proc-return [22mop‐ tions. [1m-V [22mor [1m--version[0m Displays the version number of [1mless[22m. [1m-w [22mor [1m--hilite-unread[0m - Temporarily highlights the first "new" line after a forward - movement of a full page. The first "new" line is the line imme‐ - diately following the line previously at the bottom of the - screen. Also highlights the target line after a g or p command. - The highlight is removed at the next command which causes move‐ - ment. If the [1m--status-line [22moption is in effect, the entire line - (the width of the screen) is highlighted. Otherwise, only the - text in the line is highlighted, unless the [1m-J [22moption is in ef‐ - fect, in which case only the status column is highlighted. + Temporarily highlights the first "new" line after a movement of + a full page. The first "new" line is the line immediately fol‐ + lowing the line previously at the bottom of the screen. Also + highlights the target line after a g or p command. The high‐ + light is removed at the next command which causes movement. If + the [1m--status-line [22moption is in effect, the entire line (the + width of the screen) is highlighted. Otherwise, only the text + in the line is highlighted, unless the [1m-J [22moption is in effect, + in which case only the status column is highlighted. [1m-W [22mor [1m--HILITE-UNREAD[0m Like [1m-w[22m, but temporarily highlights the first new line after any - forward movement command larger than one line. + movement command larger than one line. [1m-x[4m[22mn[24m,... or [1m--tabs=[4m[22mn[24m,... Sets tab stops. If only one [4mn[24m is specified, tab stops are set at multiples of [4mn[24m. If multiple values separated by commas are specified, tab stops are set at those positions, and then con‐ - tinue with the same spacing as the last two. For example, - "[1m-x9,17[22m" will set tabs at positions 9, 17, 25, 33, etc. The de‐ - fault for [4mn[24m is 8. + tinue with the same spacing as the last two. Position numbers + are zero‐based: the leftmost position is 0, the next is 1, etc. + For example, "[1m-x8,16[22m" is the same as "[1m-x8[22m" and sets tabs at po‐ + sition 8, 16, 24, 32, etc. "[1m-x10,14,20[22m" will set tabs at posi‐ + tion 10, 14, 20, 26, 32, etc. The default for [4mn[24m is 8. [1m-X [22mor [1m--no-init[0m Disables sending the termcap initialization and deinitialization - strings to the terminal. This is sometimes desirable if ini‐ + strings to the terminal. This is sometimes desirable if ini‐ tialization or deinitialization does something unnecessary, like - clearing the screen. Note that some terminals require the ini‐ - tialization string for proper operation, so they may not behave + clearing the screen. Note that some terminals require the ini‐ + tialization string for proper operation, so they may not behave completely correctly when [1m-X [22mis used. [1m-y[4m[22mn[24m or [1m--max-forw-scroll=[4m[22mn[0m Specifies a maximum number of lines to scroll forward. If it is necessary to scroll forward more than [4mn[24m lines, the screen is re‐ - painted instead. The [1m-c [22mor [1m-C [22moption may be used to repaint - from the top of the screen if desired. By default, any forward + painted instead. The [1m-c [22mor [1m-C [22moption may be used to repaint + from the top of the screen if desired. By default, any forward movement causes scrolling. [1m-z[4m[22mn[24m or [1m--window=[4m[22mn[24m or -[4mn[0m - Changes the default scrolling window size to [4mn[24m lines. The de‐ - fault is one screenful. The z and w commands can also be used - to change the window size. The "z" may be omitted for compati‐ - bility with some versions of [1mmore[22m(1). If the number [4mn[24m is nega‐ - tive, it indicates [4mn[24m lines less than the current screen size. - For example, if the screen is 24 lines, [1m-z-4 [22msets the scrolling + Changes the default scrolling window size to [4mn[24m lines. The de‐ + fault is one screenful. The z and w commands can also be used + to change the window size. The "z" may be omitted for compati‐ + bility with some versions of [1mmore[22m(1). If the number [4mn[24m is nega‐ + tive, it indicates [4mn[24m lines less than the current screen size. + For example, if the screen is 24 lines, [1m-z-4 [22msets the scrolling window to 20 lines. If the screen is later resized to 40 lines, the scrolling window automatically changes to 36 lines. [1m-"[4m[22mcc[24m or [1m--quotes=[4m[22mcc[0m - Changes the filename quoting character. This may be necessary - if you are trying to name a file which contains both spaces and - quote characters. Followed by a single character, this changes - the quote character to that character. Filenames containing a + Changes the filename quoting character. This may be necessary + if you are trying to name a file which contains both spaces and + quote characters. Followed by a single character, this changes + the quote character to that character. Filenames containing a space should then be surrounded by that character rather than by - double quotes. Followed by two characters, changes the open - quote to the first character, and the close quote to the second + double quotes. Followed by two characters, changes the open + quote to the first character, and the close quote to the second character. Filenames containing a space should then be preceded - by the open quote character and followed by the close quote - character. Note that even after the quote characters are - changed, this option remains -" (a dash followed by a double + by the open quote character and followed by the close quote + character. Note that even after the quote characters are + changed, this option remains -" (a dash followed by a double quote). [1m-~ [22mor [1m--tilde[0m @@ -1252,22 +1262,22 @@ [1m-# [22mor [1m--shift[0m Specifies the default number of positions to scroll horizontally - in the RIGHTARROW and LEFTARROW commands. If the number speci‐ - fied is zero, it sets the default number of positions to one + in the RIGHTARROW and LEFTARROW commands. If the number speci‐ + fied is zero, it sets the default number of positions to one half of the screen width. Alternately, the number may be speci‐ - fied as a fraction of the width of the screen, starting with a - decimal point: .5 is half of the screen width, .3 is three - tenths of the screen width, and so on. If the number is speci‐ + fied as a fraction of the width of the screen, starting with a + decimal point: .5 is half of the screen width, .3 is three + tenths of the screen width, and so on. If the number is speci‐ fied as a fraction, the actual number of scroll positions is re‐ calculated if the terminal window is resized. [1m--autosave=[4m[22mactions[0m - Normally the history file is saved only when [1mless [22mexits. This + Normally the history file is saved only when [1mless [22mexits. This option specifies other actions which will cause the history file - to be saved. Each action is defined by a single character in + to be saved. Each action is defined by a single character in the [4mactions[24m string: - m Setting or clearing a mark while [1m--save‐marks [22mis in ef‐ + m Setting or clearing a mark while [1m--save‐marks [22mis in ef‐ fect. / Searching. @@ -1277,17 +1287,84 @@ * Any action; same as "m/!". Can be set to "‐" to specify the default, that only exiting [1mless[0m - will cause the history file to be saved. Note that, depending - on your shell, if you specify this option on the command line, + will cause the history file to be saved. Note that, depending + on your shell, if you specify this option on the command line, the "!" and "*" characters may need to be escaped or quoted. [1m--cmd=[4m[22mcommands[0m - The specified string is taken to be an initial command to [1mless[22m. - This is similar to specifying "+[4mcommands[24m", except that commands - specified by [1m--cmd [22mare not executed if [1mless [22mexits immediately - due to the use of the [1m-E [22mor [1m-F [22moption, while commands specified + The specified string is taken to be an initial command to [1mless[22m. + This is similar to specifying "+[4mcommands[24m", except that commands + specified by [1m--cmd [22mare not executed if [1mless [22mexits immediately + due to the use of the [1m-E [22mor [1m-F [22moption, while commands specified by the [1m+ [22moption are executed even if [1mless [22mexits immediately. + [1m--emouse=[4m[22mfeatures[0m + [4mfeatures[24m is a comma‐separated list of mouse features to be en‐ + abled, selected from this list: + + vscroll + Scrolling the mouse wheel down or up moves forward or + backward in the file. The number of lines to scroll when + the wheel is moved can be set by the [1m--wheel-lines [22mop‐ + tion. The [1m--rmouse [22moption reverses the direction of + movement. + + vdrag Holding down the left button and dragging up or down + moves forward or backward in the file. + + hscroll + Scrolling the side scroll wheel left or right moves left + or right in the file. The number of columns to scroll + when the wheel is moved can be set by the [1m--wheel-lines[0m + option. The [1m--rmouse [22moption reverses the direction of + movement. + + hdrag Holding down the left button and dragging left or right + moves left or right in the file. + + lclick Left‐clicking sets the "#" mark to the line where the + mouse is clicked. If a left‐click is performed with the + mouse cursor on an OSC 8 hyperlink, the hyperlink is se‐ + lected as if by the ^O^N command. If a left‐click is + performed with the mouse cursor on an OSC 8 hyperlink + which is already selected, the hyperlink is opened as if + by the ^O^O command. + + rclick Right‐clicking (or clicking any button other than the + left one) returns to the "#" mark position. + + scroll Same as "vscroll,hscroll". + + drag Same as "vdrag,hdrag". + + hmove Same as "hscroll,hdrag". + + vmove Same as "vscroll,vdrag". + + move Same as "vmove,hmove". + + click Same as "lclick,rclick". + + all Same as "move,click". + + Each feature name may be abbreviated as long as the abbreviation + is unambiguous. If [4mfeatures[24m is set to "‐", all mouse features + are disabled. Mouse input works only on terminals which support + X11 mouse reporting, and on Windows. + + [1m--end-prompt=[4m[22mstring[0m + Specifies a string which is printed immediately after the prompt + is erased. As with the [1m--prompt [22moption, the first character of + the string determines which prompt the string will be printed + after ("[1ms[22m" for the short prompt, "[1mm[22m" for the medium prompt, or + "[1mM[22m" for the long prompt). Special characters in the string are + processed as described in the PROMPTS section, in the same way + as prompts specified by the [1m--prompt [22moption. If set to a dash + ([1m-[22m), nothing is printed after the prompt is erased. This option + can be useful if the prompt string has been modified to contain + an escape sequence that puts the terminal in a mode which should + be cleared when the prompt is erased. + [1m--exit-follow-on-close[0m When using the "F" command on a pipe, [1mless [22mwill automatically stop waiting for more data when the input side of the pipe is @@ -1295,54 +1372,62 @@ [1m--file-size[0m If [1m--file-size [22mis specified, [1mless [22mwill determine the size of the - file immediately after opening the file. Then the "=" command - will display the number of lines in the file. Normally this is - not done, because it can be slow if the input file is non‐seek‐ - able (such as a pipe) and is large. + file immediately after opening the file. With this option en‐ + abled, the = command and the long prompt will display the number + of lines in the file. Normally this is not done, because it can + be slow if the input file is non‐seekable (such as a pipe) and + is large. [1m--follow-name[0m Normally, if the input file is renamed while an F command is ex‐ ecuting, [1mless [22mwill continue to display the contents of the orig‐ - inal file despite its name change. If [1m--follow-name [22mis speci‐ - fied, during an F command [1mless [22mwill periodically attempt to re‐ + inal file despite its name change. If [1m--follow-name [22mis speci‐ + fied, during an F command [1mless [22mwill periodically attempt to re‐ open the file by name. If the reopen succeeds and the file is a - different file from the original (which means that a new file - has been created with the same name as the original (now re‐ + different file from the original (which means that a new file + has been created with the same name as the original (now re‐ named) file), [1mless [22mwill display the contents of that new file. [1m--form-feed[0m - When scrolling forward or backward in the file, stop if a line - beginning with a form feed character (^L) is reached. This can - be useful when viewing a file which uses form feeds between + When scrolling forward or backward in the file, stop if a line + beginning with a form feed character (^L) is reached. This can + be useful when viewing a file which uses form feeds between pages. [1m--header=[4m[22mL[24m,[4mC[24m,[4mN[0m - Sets the number of header lines and columns displayed on the - screen. The number of header lines is set to [4mL[24m. If [4mL[24m is 0, + Sets the number of header lines and columns displayed on the + screen. The number of header lines is set to [4mL[24m. If [4mL[24m is 0, header lines are disabled. If [4mL[24m is empty or missing, the number - of header lines is unchanged. The number of header columns is + of header lines is unchanged. The number of header columns is set to [4mC[24m. If [4mC[24m is 0, header columns are disabled. If [4mC[24m is emp‐ - ty or missing, the number of header columns is unchanged. The - first header line is set to line number [4mN[24m in the file. If [4mN[24m is - empty or missing, it is taken to be the number of the line cur‐ + ty or missing, the number of header columns is unchanged. The + first header line is set to line number [4mN[24m in the file. If [4mN[24m is + empty or missing, it is taken to be the number of the line cur‐ rently displayed in the first line of the screen (if the [1m--head‐[0m - [1mer [22mcommand has been issued from within [1mless[22m), or 1 (if the - [1m--header [22moption has been given on the command line). The spe‐ + [1mer [22mcommand has been issued from within [1mless[22m), or 1 (if the + [1m--header [22moption has been given on the command line). The spe‐ cial form "[1m--header=-[22m" disables header lines and header columns, and is equivalent to "[1m--header=0,0[22m". - When [4mL[24m is nonzero, the first [4mL[24m lines at the top of the screen - are replaced with the [4mL[24m lines of the file beginning at line [4mN[24m, + When [4mL[24m is nonzero, the first [4mL[24m lines at the top of the screen + are replaced with the [4mL[24m lines of the file beginning at line [4mN[24m, regardless of what part of the file is being viewed. When head‐ er lines are displayed, any file contents before the header line - cannot be viewed. When [4mC[24m is nonzero, the first [4mC[24m characters - displayed at the beginning of each line are replaced with the - first [4mC[24m characters of the line, even if the rest of the line is + cannot be viewed. When [4mC[24m is nonzero, the first [4mC[24m characters + displayed at the beginning of each line are replaced with the + first [4mC[24m characters of the line, even if the rest of the line is scrolled horizontally. - While the [1m--header [22moption is active, lines longer than the + While the [1m--header [22moption is active, lines longer than the screen width are truncated, and the [1m-S [22moption is ignored. + [1m--hilite-target[0m + Highlights the "target" line, as specified by the -j option. If + the [1m--status-line [22moption is in effect, the entire line (the + width of the screen) is highlighted. Otherwise, only the text + in the line is highlighted, unless the [1m-J [22moption is in effect, + in which case only the status column is highlighted. + [1m--incsearch[0m Subsequent search commands will be "incremental"; that is, [1mless[0m will advance to the next line containing the search pattern as @@ -1394,23 +1479,11 @@ See the [1m--tabs [22mdescription for acceptable values of [4mn[24m. [1m--mouse[0m - Enables mouse input: scrolling the mouse wheel down moves for‐ - ward in the file, scrolling the mouse wheel up moves backwards - in the file, left‐click sets the "#" mark to the line where the - mouse is clicked, and right‐click (or any other) returns to the - "#" mark position. Holding down the left button and dragging - also moves in the file. If a left‐click is performed with the - mouse cursor on an OSC 8 hyperlink, the hyperlink is selected as - if by the ^O^N command. If a left‐click is performed with the - mouse cursor on an OSC 8 hyperlink which is already selected, - the hyperlink is opened as if by the ^O^O command. The number - of lines to scroll when the wheel is moved can be set by the - [1m--wheel-lines [22moption. Mouse input works only on terminals which - support X11 mouse reporting, and on Windows. + Enabling [1m--mouse [22mis the same as [1m--emouse=vmove,click[22m. Disabling + [1m--mouse [22mis the same as [1m--emouse=‐[22m. [1m--MOUSE[0m - Like [1m--mouse[22m, except the direction scrolled on mouse wheel move‐ - ment is reversed. + Like [1m--mouse [22mwith [1m--rmouse[22m. [1m--no-edit-warn[0m Don’t print a warning message when using the v command on a file @@ -1457,6 +1530,13 @@ [1m--no-vbell[0m Disables the terminal’s visual bell. + [1m--past-eof[0m + Normally scrolling commands (other than J, K, ESC‐SPACE and ESC‐ + b) stop scrolling when end‐of‐file is reached scrolling forward, + or beginning‐of‐file is reached scrolling backward. This option + makes all scrolling commands continue past end‐of‐file or begin‐ + ning‐of‐file. + [1m--proc-backspace[0m If set, backspaces are handled as if neither the [1m-u [22moption nor the [1m-U [22moption were set. That is, a backspace adjacent to an un‐ @@ -1501,25 +1581,29 @@ an alternate screen, this makes the last screenful of the cur‐ rent file remain visible after [1mless [22mhas quit. + [1m--rmouse[0m + Reverses the normal direction of scrolling when mouse scrolling + is enabled via [1m--emouse=vscroll [22mor [1m--emouse=hscroll[22m. + [1m--rscroll=[4m[22mc[0m - This option changes the character used to mark truncated lines. + This option changes the character used to mark truncated lines. It may begin with a two‐character attribute indicator like LESS‐ - BINFMT does. If there is no attribute indicator, standout is + BINFMT does. If there is no attribute indicator, standout is used. If set to "-", truncated lines are not marked. [1m--save-marks[0m - Save marks in the history file, so marks are retained across + Save marks in the history file, so marks are retained across different invocations of [1mless[22m. [1m--search-options=[4m[22m...[0m - Sets default search modifiers. The value is a string of one or + Sets default search modifiers. The value is a string of one or more of the characters E, F, K, N, R or W. Setting any of these - has the same effect as typing that control character at the be‐ - ginning of every search pattern. For example, setting - [1m--search-options=[4m[22mW[24m is the same as typing ^W at the beginning of + has the same effect as typing that control character at the be‐ + ginning of every search pattern. For example, setting + [1m--search-options=[4m[22mW[24m is the same as typing ^W at the beginning of every pattern. The value may also contain a digit between 1 and 5, which has the same effect as typing ^S followed by that digit - at the beginning of every search pattern. The value "-" dis‐ + at the beginning of every search pattern. The value "-" dis‐ ables all default search modifiers. [1m--show-preproc-errors[0m @@ -1531,10 +1615,11 @@ fect. The default is 2 characters. [1m--status-line[0m - If a line is marked, the entire line (rather than just the sta‐ - tus column) is highlighted. Also lines highlighted due to the - [1m-w [22moption will have the entire line highlighted. If [1m--use-color[0m - is set, the line is colored rather than highlighted. + If a line is marked, the entire line (rather than just the sta‐ + tus column) is highlighted. Also lines highlighted due to the + [1m-w [22mor [1m--hilite-target [22moption will have the entire line high‐ + lighted. If [1m--use-color [22mis set, the line is colored rather than + highlighted. [1m--use-backslash[0m This option changes the interpretations of options which follow @@ -1551,9 +1636,9 @@ standards/ecma-48). [1m--wheel-lines=[4m[22mn[0m - Set the number of lines to scroll when the mouse wheel is - scrolled and the [1m--mouse [22mor [1m--MOUSE [22moption is in effect. The - default is 1 line. + Set the number of lines or columns to scroll when the mouse + wheel is scrolled and the [1m--mouse [22mor [1m--MOUSE [22moption is in ef‐ + fect. The default is 1 line or column. [1m--wordwrap[0m When the [1m-S [22moption is not in use, wrap each line at a space or @@ -1616,7 +1701,7 @@ Delete the character to the left of the cursor, or cancel the command if the command line is empty. - DELETE or [ ESC‐x ] + DELETE [ ESC‐x ] Delete the character under the cursor. ^BACKSPACE [ ESC‐BACKSPACE ] @@ -1639,7 +1724,7 @@ TAB Complete the partial filename to the left of the cursor. If it matches more than one filename, the first match is entered into - the command line. Repeated TABs will cycle thru the other + the command line. Repeated TABs will cycle through the other matching filenames. If the completed filename is a directory, a "/" is appended to the filename. (On MS‐DOS and Windows sys‐ tems, a "\" is appended.) The environment variable LESSSEPARA‐ @@ -1647,93 +1732,93 @@ directory name. BACKTAB (SHIFT‐TAB) [ ESC‐TAB ] - Like TAB, but cycles in the reverse direction thru the matching - filenames. + Like TAB, but cycles in the reverse direction through the match‐ + ing filenames. - ^L Complete the partial filename to the left of the cursor. If it + ^L Complete the partial filename to the left of the cursor. If it matches more than one filename, all matches are entered into the command line (if they fit). ^U (Unix and OS/2) or ESC (MS‐DOS and Windows) - Delete the entire command line, or cancel the command if the - cursor is at the beginning of the command line. If you have + Delete the entire command line, or cancel the command if the + cursor is at the beginning of the command line. If you have changed your line‐kill character in Unix to something other than ^U, that character is used instead of ^U. ^G Delete the entire command line and return to the main prompt. [1mKEY BINDINGS[0m - You may define your own [1mless [22mcommands by creating a lesskey source - file. This file specifies a set of command keys and an action associ‐ - ated with each key. You may also change the line‐editing keys (see - LINE EDITING), and set environment variables used by [1mless[22m. See the + You may define your own [1mless [22mcommands by creating a lesskey source + file. This file specifies a set of command keys and an action associ‐ + ated with each key. You may also change the line‐editing keys (see + LINE EDITING), and set environment variables used by [1mless[22m. See the [1mlesskey[22m(1) manual page for details about the file format. - If the environment variable LESSKEYIN is set, [1mless [22muses that as the - name of the lesskey source file. Otherwise, [1mless [22mlooks in a standard - place for the lesskey source file: On Unix systems, [1mless [22mlooks for a - lesskey file called "$XDG_CONFIG_HOME/lesskey" or "$HOME/.con‐ - fig/lesskey" or "$HOME/.lesskey". On MS‐DOS and Windows systems, [1mless[0m - looks for a lesskey file called "$HOME/_lesskey", and if it is not + If the environment variable LESSKEYIN is set, [1mless [22muses that as the + name of the lesskey source file. Otherwise, [1mless [22mlooks in a standard + place for the lesskey source file: On Unix systems, [1mless [22mlooks for a + lesskey file called "$XDG_CONFIG_HOME/lesskey" or "$HOME/.con‐ + fig/lesskey" or "$HOME/.lesskey". On MS‐DOS and Windows systems, [1mless[0m + looks for a lesskey file called "$HOME/_lesskey", and if it is not found there, then looks for a lesskey file called "_lesskey" in any di‐ - rectory specified in the PATH environment variable. On OS/2 systems, - [1mless [22mlooks for a lesskey file called "$HOME/lesskey.ini", and if it is - not found, then looks for a lesskey file called "lesskey.ini" in any - directory specified in the INIT environment variable, and if it not - found there, then looks for a lesskey file called "lesskey.ini" in any + rectory specified in the PATH environment variable. On OS/2 systems, + [1mless [22mlooks for a lesskey file called "$HOME/lesskey.ini", and if it is + not found, then looks for a lesskey file called "lesskey.ini" in any + directory specified in the INIT environment variable, and if it not + found there, then looks for a lesskey file called "lesskey.ini" in any directory specified in the PATH environment variable. - A system‐wide lesskey source file may also be set up to provide key - bindings. If a key is defined in both a local lesskey file and in the - system‐wide file, key bindings in the local file take precedence over - those in the system‐wide file. If the environment variable - LESSKEYIN_SYSTEM is set, [1mless [22muses that as the name of the system‐wide - lesskey file. Otherwise, [1mless [22mlooks in a standard place for the sys‐ + A system‐wide lesskey source file may also be set up to provide key + bindings. If a key is defined in both a local lesskey file and in the + system‐wide file, key bindings in the local file take precedence over + those in the system‐wide file. If the environment variable + LESSKEYIN_SYSTEM is set, [1mless [22muses that as the name of the system‐wide + lesskey file. Otherwise, [1mless [22mlooks in a standard place for the sys‐ tem‐wide lesskey file: On Unix systems, the system‐wide lesskey file is - /usr/local/etc/syslesskey. (However, if [1mless [22mwas built with a differ‐ - ent sysconf directory than /usr/local/etc, that directory is where the + /usr/local/etc/syslesskey. (However, if [1mless [22mwas built with a differ‐ + ent sysconf directory than /usr/local/etc, that directory is where the sysless file is found.) On MS‐DOS and Windows systems, the system‐wide - lesskey file is c:\_syslesskey. On OS/2 systems, the system‐wide + lesskey file is c:\_syslesskey. On OS/2 systems, the system‐wide lesskey file is c:\syslesskey.ini. - Older versions of [1mless [22m(before v582) used lesskey files with a binary - format, produced by the [1mlesskey [22mprogram. It is no longer necessary to + Older versions of [1mless [22m(before v582) used lesskey files with a binary + format, produced by the [1mlesskey [22mprogram. It is no longer necessary to use the [1mlesskey [22mprogram. [1mINPUT PREPROCESSOR[0m - You may define an "input preprocessor" for [1mless[22m. Before [1mless [22mopens a - file, it first gives the input preprocessor a chance to modify the way - the contents of the file are displayed. An input preprocessor is sim‐ - ply an executable program (or shell script), which writes the contents + You may define an "input preprocessor" for [1mless[22m. Before [1mless [22mopens a + file, it first gives the input preprocessor a chance to modify the way + the contents of the file are displayed. An input preprocessor is sim‐ + ply an executable program (or shell script), which writes the contents of the file to a different file, called the replacement file. The con‐ - tents of the replacement file are then displayed in place of the con‐ - tents of the original file. However, it will appear to the user as if - the original file is opened; that is, [1mless [22mwill display the original + tents of the replacement file are then displayed in place of the con‐ + tents of the original file. However, it will appear to the user as if + the original file is opened; that is, [1mless [22mwill display the original filename as the name of the current file. - An input preprocessor receives one command line argument, the original - filename, as entered by the user. It should create the replacement - file, and when finished, print the name of the replacement file to its - standard output. If the input preprocessor does not output a replace‐ - ment filename, [1mless [22muses the original file, as normal. The input pre‐ - processor is not called when viewing standard input. To set up an in‐ - put preprocessor, set the LESSOPEN environment variable to a command - line which will invoke your input preprocessor. This command line - should include one occurrence of the string "%s", which will be re‐ + An input preprocessor receives one command line argument, the original + filename, as entered by the user. It should create the replacement + file, and when finished, print the name of the replacement file to its + standard output. If the input preprocessor does not output a replace‐ + ment filename, [1mless [22muses the original file, as normal. The input pre‐ + processor is not called when viewing standard input. To set up an in‐ + put preprocessor, set the LESSOPEN environment variable to a command + line which will invoke your input preprocessor. This command line + should include one occurrence of the string "%s", which will be re‐ placed by the filename when the input preprocessor command is invoked. When [1mless [22mcloses a file opened in such a way, it will call another pro‐ - gram, called the input postprocessor, which may perform any desired - clean‐up action (such as deleting the replacement file created by + gram, called the input postprocessor, which may perform any desired + clean‐up action (such as deleting the replacement file created by LESSOPEN). This program receives two command line arguments, the orig‐ - inal filename as entered by the user, and the name of the replacement - file. To set up an input postprocessor, set the LESSCLOSE environment - variable to a command line which will invoke your input postprocessor. - It may include two occurrences of the string "%s"; the first is re‐ - placed with the original name of the file and the second with the name + inal filename as entered by the user, and the name of the replacement + file. To set up an input postprocessor, set the LESSCLOSE environment + variable to a command line which will invoke your input postprocessor. + It may include two occurrences of the string "%s"; the first is re‐ + placed with the original name of the file and the second with the name of the replacement file, which was output by LESSOPEN. - For example, on many Unix systems, these two scripts will allow you to + For example, on many Unix systems, these two scripts will allow you to keep files in compressed format, but still let [1mless [22mview them directly: lessopen.sh: @@ -1753,27 +1838,27 @@ #! /bin/sh rm $2 - To use these scripts, put them both where they can be executed and set + To use these scripts, put them both where they can be executed and set LESSOPEN="lessopen.sh %s", and LESSCLOSE="lessclose.sh %s %s". More - complex LESSOPEN and LESSCLOSE scripts may be written to accept other + complex LESSOPEN and LESSCLOSE scripts may be written to accept other types of compressed files, and so on. - It is also possible to set up an input preprocessor to pipe the file - data directly to [1mless[22m, rather than putting the data into a replacement + It is also possible to set up an input preprocessor to pipe the file + data directly to [1mless[22m, rather than putting the data into a replacement file. This avoids the need to decompress the entire file before start‐ ing to view it. An input preprocessor that works this way is called an - input pipe. An input pipe, instead of writing the name of a replace‐ + input pipe. An input pipe, instead of writing the name of a replace‐ ment file on its standard output, writes the entire contents of the re‐ - placement file on its standard output. If the input pipe does not - write any characters on its standard output, then there is no replace‐ - ment file and [1mless [22muses the original file, as normal. To use an input - pipe, make the first character in the LESSOPEN environment variable a - vertical bar (|) to signify that the input preprocessor is an input - pipe. As with non‐pipe input preprocessors, the command string must - contain one occurrence of %s, which is replaced with the filename of + placement file on its standard output. If the input pipe does not + write any characters on its standard output, then there is no replace‐ + ment file and [1mless [22muses the original file, as normal. To use an input + pipe, make the first character in the LESSOPEN environment variable a + vertical bar (|) to signify that the input preprocessor is an input + pipe. As with non‐pipe input preprocessors, the command string must + contain one occurrence of %s, which is replaced with the filename of the input file. - For example, on many Unix systems, this script will work like the pre‐ + For example, on many Unix systems, this script will work like the pre‐ vious example scripts: lesspipe.sh: @@ -1790,29 +1875,29 @@ LESSOPEN="|lesspipe.sh %s". Note that a preprocessor cannot output an empty file, since that is in‐ - terpreted as meaning there is no replacement, and the original file is - used. To avoid this, if LESSOPEN starts with two vertical bars, the - exit status of the script determines the behavior when the output is - empty. If the output is empty and the exit status is zero, the empty - output is considered to be replacement text. If the output is empty + terpreted as meaning there is no replacement, and the original file is + used. To avoid this, if LESSOPEN starts with two vertical bars, the + exit status of the script determines the behavior when the output is + empty. If the output is empty and the exit status is zero, the empty + output is considered to be replacement text. If the output is empty and the exit status is nonzero, the original file is used. For compat‐ - ibility with previous versions of [1mless[22m, if LESSOPEN starts with only + ibility with previous versions of [1mless[22m, if LESSOPEN starts with only one vertical bar, the exit status of the preprocessor is ignored. - When an input pipe is used, a LESSCLOSE postprocessor can be used, but + When an input pipe is used, a LESSCLOSE postprocessor can be used, but it is usually not necessary since there is no replacement file to clean - up. In this case, the replacement file name passed to the LESSCLOSE + up. In this case, the replacement file name passed to the LESSCLOSE postprocessor is "-". - For compatibility with previous versions of [1mless[22m, the input preproces‐ + For compatibility with previous versions of [1mless[22m, the input preproces‐ sor or pipe is not used if [1mless [22mis viewing standard input. However, if - the first character of LESSOPEN is a dash (-), the input preprocessor - is used on standard input as well as other files. In this case, the - dash is not considered to be part of the preprocessor command. If + the first character of LESSOPEN is a dash ([1m-[22m), the input preprocessor + is used on standard input as well as other files. In this case, the + dash is not considered to be part of the preprocessor command. If standard input is being viewed, the input preprocessor is passed a file - name consisting of a single dash. Similarly, if the first two charac‐ - ters of LESSOPEN are vertical bar and dash (|-) or two vertical bars - and a dash (||-), the input pipe is used on standard input as well as + name consisting of a single dash. Similarly, if the first two charac‐ + ters of LESSOPEN are vertical bar and dash ([1m|-[22m) or two vertical bars + and a dash ([1m||-[22m), the input pipe is used on standard input as well as other files. Again, in this case the dash is not considered to be part of the input pipe command. @@ -1823,11 +1908,11 @@ can be displayed directly to the screen. control characters - should not be displayed directly, but are expected to be found + should not be displayed directly, but are expected to be found in ordinary text files (such as backspace and tab). binary characters - should not be displayed directly and are not expected to be + should not be displayed directly and are not expected to be found in text files. composing characters @@ -1838,17 +1923,17 @@ are simply deleted from the input and not displayed. (Only when LESSCHARSET is "utf8".) - A "character set" is a description of which of these categories each + A "character set" is a description of which of these categories each character belongs to. The LESSCHARSET environment variable may be used to select a character set. Possible values for LESSCHARSET are: - ascii BS, TAB, NL, CR, and formfeed are control characters, all chars - with values between 32 and 126 are normal, and all others are + ascii BS, TAB, NL, CR, and formfeed are control characters, all chars + with values between 32 and 126 are normal, and all others are binary. iso8859 - Selects an ISO 8859 character set. This is the same as ASCII, - except characters between 160 and 255 are treated as normal + Selects an ISO 8859 character set. This is the same as ASCII, + except characters between 160 and 255 are treated as normal characters. latin1 Same as iso8859. @@ -1860,8 +1945,8 @@ ebcdic Selects an EBCDIC character set. IBM-1047 - Selects an EBCDIC character set used by OS/390 Unix Services. - This is the EBCDIC analogue of latin1. You get similar results + Selects an EBCDIC character set used by OS/390 Unix Services. + This is the EBCDIC analogue of latin1. You get similar results by setting either LESSCHARSET=IBM-1047 or LC_CTYPE=en_US in your environment. @@ -1869,29 +1954,29 @@ next Selects a character set appropriate for NeXT computers. - utf-8 Selects the UTF‐8 encoding of the ISO 10646 character set. - UTF‐8 is special in that it supports multi‐byte characters in + utf-8 Selects the UTF‐8 encoding of the ISO 10646 character set. + UTF‐8 is special in that it supports multi‐byte characters in the input file. It is the only character set that supports mul‐ ti‐byte characters. windows - Selects a character set appropriate for Microsoft Windows (cp + Selects a character set appropriate for Microsoft Windows (cp 1252). - In rare cases, it may be desired to tailor [1mless [22mto use a character set - other than the ones definable by LESSCHARSET. In this case, the envi‐ + In rare cases, it may be desired to tailor [1mless [22mto use a character set + other than the ones definable by LESSCHARSET. In this case, the envi‐ ronment variable LESSCHARDEF can be used to define a character set. It should be set to a string where each character in the string represents - one character in the character set. The character "." is used for a - normal character, "c" for control, and "b" for binary. A decimal num‐ - ber may be used for repetition. For example, "bccc4b." would mean - character 0 is binary, 1, 2 and 3 are control, 4, 5, 6 and 7 are bina‐ + one character in the character set. The character "." is used for a + normal character, "c" for control, and "b" for binary. A decimal num‐ + ber may be used for repetition. For example, "bccc4b." would mean + character 0 is binary, 1, 2 and 3 are control, 4, 5, 6 and 7 are bina‐ ry, and 8 is normal. All characters after the last are taken to be the - same as the last, so characters 9 through 255 would be normal. (This - is an example, and does not necessarily represent any real character + same as the last, so characters 9 through 255 would be normal. (This + is an example, and does not necessarily represent any real character set.) - This table shows the value of LESSCHARDEF which is equivalent to each + This table shows the value of LESSCHARDEF which is equivalent to each of the possible values for LESSCHARSET: ascii 8bcccbcc18b95.b dos 8bcccbcc12bc5b95.b. @@ -1904,57 +1989,57 @@ latin1 8bcccbcc18b95.33b. next 8bcccbcc18b95.bb125.bb - If neither LESSCHARSET nor LESSCHARDEF is set, but any of the strings - "UTF-8", "UTF8", "utf-8" or "utf8" is found in the LC_ALL, LC_CTYPE or + If neither LESSCHARSET nor LESSCHARDEF is set, but any of the strings + "UTF-8", "UTF8", "utf-8" or "utf8" is found in the LC_ALL, LC_CTYPE or LANG environment variables, then the default character set is utf-8. - If that string is not found, but your system supports the [1msetlocale[22m(3) - interface, [1mless [22mwill use setlocale to determine the character set. - setlocale is controlled by setting the LANG or LC_CTYPE environment + If that string is not found, but your system supports the [1msetlocale[22m(3) + interface, [1mless [22mwill use setlocale to determine the character set. + setlocale is controlled by setting the LANG or LC_CTYPE environment variables. - Finally, if the [1msetlocale [22minterface is also not available, the default + Finally, if the [1msetlocale [22minterface is also not available, the default character set is utf-8. - Control and binary characters are displayed in standout (reverse + Control and binary characters are displayed in standout (reverse video). Each such character is displayed in caret notation if possible - (e.g. ^A for control‐A). Caret notation is used only if inverting the + (e.g. ^A for control‐A). Caret notation is used only if inverting the 0100 bit results in a normal printable character. Otherwise, the char‐ - acter is displayed as a hex number in angle brackets. This format can - be changed by setting the LESSBINFMT environment variable. LESSBINFMT + acter is displayed as a hex number in angle brackets. This format can + be changed by setting the LESSBINFMT environment variable. LESSBINFMT may begin with a "*" and one character to select the display attribute: - "*k" is blinking, "*d" is bold, "*u" is underlined, "*s" is standout, - and "*n" is normal. If LESSBINFMT does not begin with a "*", normal - attribute is assumed. The remainder of LESSBINFMT is a string which - may include one printf‐style escape sequence (a % followed by x, X, o, - d, etc.). For example, if LESSBINFMT is "*u[%x]", binary characters - are displayed in underlined hexadecimal surrounded by brackets. The - default if no LESSBINFMT is specified is "*s<%02X>". Warning: the re‐ - sult of expanding the character via LESSBINFMT must be less than 31 + "*k" is blinking, "*d" is bold, "*u" is underlined, "*s" is standout, + and "*n" is normal. If LESSBINFMT does not begin with a "*", normal + attribute is assumed. The remainder of LESSBINFMT is a string which + may include one printf‐style escape sequence (a % followed by x, X, o, + d, etc.). For example, if LESSBINFMT is "*u[%x]", binary characters + are displayed in underlined hexadecimal surrounded by brackets. The + default if no LESSBINFMT is specified is "*s<%02X>". Warning: the re‐ + sult of expanding the character via LESSBINFMT must be less than 31 characters. When the character set is utf-8, the LESSUTFBINFMT environment variable acts similarly to LESSBINFMT but it applies to Unicode code points that - were successfully decoded but are unsuitable for display (e.g., unas‐ - signed code points). Its default value is "<U+%04lX>". Note that - LESSUTFBINFMT and LESSBINFMT share their display attribute setting - ("*x") so specifying one will affect both; LESSUTFBINFMT is read after - LESSBINFMT so its setting, if any, will have priority. Problematic - octets in a UTF‐8 file (octets of a truncated sequence, octets of a - complete but non‐shortest form sequence, invalid octets, and stray - trailing octets) are displayed individually using LESSBINFMT so as to + were successfully decoded but are unsuitable for display (e.g., unas‐ + signed code points). Its default value is "<U+%04lX>". Note that + LESSUTFBINFMT and LESSBINFMT share their display attribute setting + ("*x") so specifying one will affect both; LESSUTFBINFMT is read after + LESSBINFMT so its setting, if any, will have priority. Problematic + octets in a UTF‐8 file (octets of a truncated sequence, octets of a + complete but non‐shortest form sequence, invalid octets, and stray + trailing octets) are displayed individually using LESSBINFMT so as to facilitate diagnostic of how the UTF‐8 file is ill‐formed. - When the character set is utf-8, in rare cases it may be desirable to + When the character set is utf-8, in rare cases it may be desirable to override the Unicode definition of the type of certain characters. For example, characters in a Private Use Area are normally treated as bina‐ - ry characters, but if you are using a custom font with printable char‐ - acters in that range, it may be desirable to tell [1mless [22mto treat such + ry characters, but if you are using a custom font with printable char‐ + acters in that range, it may be desirable to tell [1mless [22mto treat such characters as printable. This can be done by setting the LESSUTFCHARD‐ EF environment variable to a comma‐separated list of [4mcharacter[24m [4mtype[24m de‐ finitions. Each character type definition consists of either one hexa‐ decimal codepoint or a pair of codepoints separated by a dash, followed - by a colon and a type character. Each hexadecimal codepoint may op‐ + by a colon and a type character. Each hexadecimal codepoint may op‐ tionally be preceded by a "U" or "U+". If a pair of codepoints is giv‐ en, the type is set for all characters inclusively between the two val‐ ues. If there are multiple comma‐separated codepoint values, they must @@ -1968,7 +2053,7 @@ c A composing (zero width) character. - d A deleted character (deleted from the input and not dis‐ + d A deleted character (deleted from the input and not dis‐ played). For example, setting LESSUTFCHARDEF to @@ -1977,78 +2062,74 @@ would make all Private Use Area characters be treated as printable. - By default, emoji modifiers, components and variation selectors are - deleted because many terminals do not display them correctly. If you - use a terminal which does display some or all of them correctly, you - can cause them to be displayed by setting LESSUTFCHARDEF to treat them - as composing characters. For example, this sets them all to composing + By default, emoji modifiers, components and variation selectors are + deleted because many terminals do not display them correctly. If you + use a terminal which does display some or all of them correctly, you + can cause them to be displayed by setting LESSUTFCHARDEF to treat them + as composing characters. For example, this sets them all to composing characters: FE00-FE0F:c,1F3FB-1F3FF:c,1F9B0-1F9B3:c,E0100-E01EF:c [1mPROMPTS[0m - The [1m-P [22moption allows you to tailor the prompt to your preference. The - string given to the [1m-P [22moption replaces the specified prompt string. + The [1m-P [22moption allows you to tailor the prompt to your preference. The + string given to the [1m-P [22moption replaces the specified prompt string. Certain characters in the string are interpreted specially. The prompt - mechanism is rather complicated to provide flexibility, but the ordi‐ - nary user need not understand the details of constructing personalized + mechanism is rather complicated to provide flexibility, but the ordi‐ + nary user need not understand the details of constructing personalized prompt strings. - A percent sign followed by a single character is expanded according to - what the following character is. (References to the input file size + A percent sign followed by a single character is expanded according to + what the following character is. (References to the input file size below refer to the preprocessed size, if an input preprocessor is being used.) - %b[4mX[24m Replaced by the byte offset into the current input file. The b + %b[4mX[24m Replaced by the byte offset into the current input file. The b is followed by a single character (shown as [4mX[24m above) which spec‐ - ifies the line whose byte offset is to be used. If the charac‐ - ter is a "t", the byte offset of the top line in the display is + ifies the line whose byte offset is to be used. If the charac‐ + ter is a "t", the byte offset of the top line in the display is used, an "m" means use the middle line, a "b" means use the bot‐ - tom line, a "B" means use the line just after the bottom line, - and a "j" means use the "target" line, as specified by the [1m-j[0m + tom line, a "B" means use the line just after the bottom line, + and a "j" means use the "target" line, as specified by the [1m-j[0m option. %B Replaced by the size of the current input file. - %c Replaced by the column number of the text which appears in the + %c Replaced by the column number of the text which appears in the first column of the screen. - %C Replaced by the column number of the text which appears (or + %C Replaced by the column number of the text which appears (or would appear) in the last column of the screen. - %d[4mX[24m Replaced by the page number of a line in the input file. The + %d[4mX[24m Replaced by the page number of a line in the input file. The line to be used is determined by the [4mX[24m, as with the %b option. - %D Replaced by the number of pages in the input file, or equiva‐ + %D Replaced by the number of pages in the input file, or equiva‐ lently, the page number of the last line in the input file. - %E Replaced by the name of the editor (from the VISUAL environment - variable, or the EDITOR environment variable if VISUAL is not + %E Replaced by the name of the editor (from the VISUAL environment + variable, or the EDITOR environment variable if VISUAL is not defined). See the discussion of the LESSEDIT feature below. %f Replaced by the name of the current input file. - %F Replaced by the last component of the name of the current input + %F Replaced by the last component of the name of the current input file. - %g Replaced by the shell‐escaped name of the current input file. - This is useful when the expanded string will be used in a shell + %g Replaced by the shell‐escaped name of the current input file. + This is useful when the expanded string will be used in a shell command, such as in LESSEDIT. - %i Replaced by the index of the current file in the list of input + %i Replaced by the index of the current file in the list of input files. - %l[4mX[24m Replaced by the line number of a line in the input file. The + %l[4mX[24m Replaced by the line number of a line in the input file. The line to be used is determined by the [4mX[24m, as with the %b option. %L Replaced by the line number of the last line in the input file. %m Replaced by the total number of input files. - %o Replaced by the URI of the currently selected OSC 8 hyperlink, - or a question mark if no hyperlink is selected. This is used by - OSC 8 handlers as explained in the ^O^O command description. - %p[4mX[24m Replaced by the percent into the current input file, based on byte offsets. The line used is determined by the [4mX[24m as with the %b option. @@ -2097,7 +2178,7 @@ ?B True if the size of current input file is known. - ?c True if the text is horizontally shifted (%c is not zero). + ?c True if the text is horizontally shifted (%c is greater than 1). ?d[4mX[24m True if the page number of the specified line is known. @@ -2114,6 +2195,8 @@ ?n True if this is the first prompt in a new input file. + ?O True if an OSC 8 hyperlink is selected. + ?p[4mX[24m True if the percent into the current input file, based on byte offsets, of the specified line is known. @@ -2428,23 +2511,27 @@ LESS_IS_MORE Emulate the [1mmore[22m(1) command. - LESS_OSC8_xxx + LESS_OSC8_OPEN_xxx Where "xxx" is a URI scheme such as "http" or "file", sets an OSC 8 handler for opening OSC 8 links containing a URI with that scheme. - LESS_OSC8_ANY + LESS_OSC8_OPEN_ANY Sets an OSC 8 handler for opening OSC 8 links for which there is - no specific LESS_OSC8_xxx handler set for the "xxx" scheme. + no specific LESS_OSC8_OPEN_xxx handler set for the "xxx" scheme. + + LESS_OSC8_OPEN_NONE + Sets an OSC 8 handler for opening OSC 8 links which contain no + scheme (that is, there is no colon in the URI). LESS_SHELL_LINES - When the [1m-F [22moption is set, [1mless [22mexits automatically if the num‐ - ber of screen lines used to display the file is less than or - equal to the screen height minus the value of the - LESS_SHELL_LINES variable. Thus, if you use a shell prompt - which occupies more than one screen line, this variable can be - set to the number of lines used by your prompt, to ensure that - the entire file can be seen when [1m-F [22mis used. If not set, + When the [1m-F [22moption is set, [1mless [22mexits automatically if the num‐ + ber of screen lines used to display the file is less than or + equal to the screen height minus the value of the + LESS_SHELL_LINES variable. Thus, if you use a shell prompt + which occupies more than one screen line, this variable can be + set to the number of lines used by your prompt, to ensure that + the entire file can be seen when [1m-F [22mis used. If not set, LESS_SHELL_LINES is assumed to be 1. LESS_SIGUSR1 @@ -2452,20 +2539,20 @@ commands will be executed when [1mless [22mreceives a SIGUSR1 signal. LESS_TERMCAP_xx - Where "xx" is any two characters, overrides the definition of - the termcap "xx" capability for the terminal. No escape se‐ + Where "xx" is any two characters, overrides the definition of + the termcap "xx" capability for the terminal. No escape se‐ quences in the string are processed, so any nonprintable charac‐ ters such as ESC must be in the string literally. LESS_TERMINFO_xxxx - Where "xxxx" is any string of characters, overrides the defini‐ - tion of the terminfo "xxxx" capability for the terminal. You + Where "xxxx" is any string of characters, overrides the defini‐ + tion of the terminfo "xxxx" capability for the terminal. You can use either LESS_TERMCAP_xx or LESS_TERMINFO_xxxx to override - a terminal capability, regardless of whether [1mless [22mis built with + a terminal capability, regardless of whether [1mless [22mis built with the [1mtermcap [22mor the [1mterminfo [22mlibrary. LESS_TERMCAP_BRACKETED_PASTE_START - Overrides the standard ANSI escape sequence to enable bracketed + Overrides the standard ANSI escape sequence to enable bracketed paste. This is used when the [1m--no-paste [22moption is in effect. LESS_TERMCAP_BRACKETED_PASTE_END @@ -2473,7 +2560,7 @@ paste. LESS_TERMCAP_MOUSE_START - Overrides the standard ANSI escape sequence to enable mouse re‐ + Overrides the standard ANSI escape sequence to enable mouse re‐ porting. This is used when the [1m--mouse [22moption is in effect. LESS_TERMCAP_MOUSE_END @@ -2481,42 +2568,42 @@ porting. LESS_TERMCAP_SUSPEND - Defines an escape sequence to temporarily suspend screen up‐ + Defines an escape sequence to temporarily suspend screen up‐ dates. This is sent to the terminal before clearing the screen. - This can be used to avoid screen tearing when the screen is re‐ + This can be used to avoid screen tearing when the screen is re‐ drawn on certain terminals. LESS_TERMCAP_RESUME - Defines an escape sequence to resume screen updates. This is + Defines an escape sequence to resume screen updates. This is sent to the terminal after displaying the prompt. LESS_UNSUPPORT - A space‐separated list of command line options. These options - will be ignored (with no error message) if they appear on the + A space‐separated list of command line options. These options + will be ignored (with no error message) if they appear on the command line or in the LESS environment variable. Options list‐ - ed in LESS_UNSUPPORT can still be changed by the - and -- com‐ - mands. Each option in LESS_UNSUPPORT is a dash followed by a + ed in LESS_UNSUPPORT can still be changed by the - and -- com‐ + mands. Each option in LESS_UNSUPPORT is a dash followed by a single character option letter, or two dashes followed by a long option name. - LINES Sets the number of lines on the screen. Takes precedence over + LINES Sets the number of lines on the screen. Takes precedence over the number of lines specified by the TERM variable. (But if you - have a windowing system which supports TIOCGWINSZ or WIOCGETD, - the window system’s idea of the screen size takes precedence + have a windowing system which supports TIOCGWINSZ or WIOCGETD, + the window system’s idea of the screen size takes precedence over the LINES and COLUMNS environment variables.) - MORE Options which are passed to [1mless [22mautomatically when running in + MORE Options which are passed to [1mless [22mautomatically when running in [1mmore[22m‐compatible mode. - PATH User’s search path (used to find a lesskey file on MS‐DOS, Win‐ + PATH User’s search path (used to find a lesskey file on MS‐DOS, Win‐ dows, and OS/2 systems). POSIXLY_CORRECT - If set to any value, all option arguments on the command line + If set to any value, all option arguments on the command line are expected to appear before any filename arguments. This must be set as an actual environment variable, not in a [1mlesskey [22mfile. - SHELL The shell used to execute the ! command, as well as to expand + SHELL The shell used to execute the ! command, as well as to expand filenames. TERM The type of terminal on which [1mless [22mis being run. @@ -2528,11 +2615,11 @@ tion. XDG_DATA_HOME - Possible location of the history file; see the description of + Possible location of the history file; see the description of the LESSHISTFILE environment variable. XDG_STATE_HOME - Possible location of the history file; see the description of + Possible location of the history file; see the description of the LESSHISTFILE environment variable. [1mSEE ALSO[0m @@ -2541,19 +2628,19 @@ [1mCOPYRIGHT[0m Copyright (C) 1984‐2026 Mark Nudelman - less is part of the GNU project and is free software. You can redis‐ - tribute it and/or modify it under the terms of either (1) the GNU Gen‐ - eral Public License as published by the Free Software Foundation; or + less is part of the GNU project and is free software. You can redis‐ + tribute it and/or modify it under the terms of either (1) the GNU Gen‐ + eral Public License as published by the Free Software Foundation; or (2) the Less License. See the file README in the less distribution for more details regarding redistribution. You should have received a copy - of the GNU General Public License along with the source for less; see - the file COPYING. If not, write to the Free Software Foundation, 59 - Temple Place, Suite 330, Boston, MA 02111‐1307, USA. You should also + of the GNU General Public License along with the source for less; see + the file COPYING. If not, write to the Free Software Foundation, 59 + Temple Place, Suite 330, Boston, MA 02111‐1307, USA. You should also have received a copy of the Less License; see the file LICENSE. less is distributed in the hope that it will be useful, but WITHOUT ANY - WARRANTY; without even the implied warranty of MERCHANTABILITY or FIT‐ - NESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + WARRANTY; without even the implied warranty of MERCHANTABILITY or FIT‐ + NESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. [1mAUTHOR[0m @@ -2562,4 +2649,4 @@ For more information, see the less homepage at https://greenwoodsoftware.com/less. -less 692 29 Jan 2026 [4mLESS[24m(1) +less 704 30 May 2026 [4mLESS[24m(1) @@ -1,5 +1,5 @@ '\" t -.TH LESS 1 "29 Jan 2026" "less 692" +.TH LESS 1 "30 May 2026" "less 704" .\" Define a string for the caret ("hat") as portably as possible. .ie \n(.g .ds ^ \(ha .el .ds ^ ^ @@ -268,6 +268,7 @@ go backward to the < which matches the > in the bottom displayed line. .IP m Followed by any lowercase or uppercase letter, marks the first displayed line with that letter. +If a number N is given, line number N is marked instead. If the status column is enabled via the .B "\-J" option, @@ -275,6 +276,7 @@ the status column shows the marked line. .IP M Acts like m, except the last displayed line is marked rather than the first displayed line. +If a number N is given, line number N is marked instead. .IP "\*'" (Single quote.) Followed by any lowercase or uppercase letter, returns to the position which @@ -283,6 +285,14 @@ Followed by another single quote, returns to the position at which the last "large" movement command was executed. Followed by a \*^ or $, jumps to the beginning or end of the file respectively. +If a number N is given, the marked line is placed on the N-th line +on the screen. +Otherwise, it is placed on the same line that it was on when it was marked +(the first line on the screen if marked via the +.B m +command, the last line on the screen if marked via the +.B M +command, or the line that was clicked if marked via the mouse). Marks are preserved when a new file is examined within a single invocation of .BR less , so the \*' command can be used to switch between input files. @@ -295,7 +305,7 @@ Same as single quote. .IP "ESC-m" Followed by any lowercase or uppercase letter, clears the mark identified by that letter. -.IP /pattern +.IP "/\fIpattern\fP" Search forward in the file for the N-th line containing the pattern. N defaults to 1. The pattern is a regular expression, as recognized by @@ -360,7 +370,7 @@ If the \*^W modifier is set, the \*^E modifier is ignored. The next character is taken literally; that is, it becomes part of the pattern even if it is one of the above search modifier characters. .RE -.IP ?pattern +.IP "?\fIpattern\fP" Search backward in the file for the N-th line containing the pattern. The search starts at the last line displayed (but see the @@ -401,9 +411,9 @@ current file up to the line where it started. .IP "\*^L" As in forward searches. .RE -.IP "ESC-/pattern" +.IP "ESC-/\fIpattern\fP" Same as "/*". -.IP "ESC-?pattern" +.IP "ESC-?\fIpattern\fP" Same as "?*". .IP n Repeat previous search, for N-th line containing the last pattern. @@ -430,6 +440,7 @@ Turn off highlighting of strings matching the current search pattern. If highlighting is already off because of a previous ESC-u command, turn highlighting back on. Any search command will also turn highlighting back on. +Also unselects any OSC 8 hyperlink that is currently selected. (Highlighting can also be disabled by toggling the .B "\-G" option; @@ -440,9 +451,9 @@ If the status column is enabled via the .B "\-J" option, this clears all search matches marked in the status column. -.IP "&pattern" +.IP "&\fIpattern\fP" Display only lines which match the pattern; -lines which do not match the pattern are not displayed. +lines which do not match the pattern are hidden. If pattern is empty (if you type & immediately followed by ENTER), any filtering is turned off, and all lines are displayed. While filtering is in effect, an ampersand is displayed at the @@ -459,13 +470,13 @@ Display only lines which do NOT match the pattern. Don't interpret regular expression metacharacters; that is, do a simple textual comparison. .RE -.IP ":e [filename]" +.IP ":e [\fIfilename\fP]" Examine a new file. If the filename is missing, the "current" file (see the :n and :p commands below) from the list of files in the command line is re-examined. -A percent sign (%) in the filename is replaced by the name of the -current file. -A pound sign (#) is replaced by the name of the previously examined file. +A percent sign (%) in the filename is replaced by the +shell-escaped name of the current file. +A pound sign (#) is replaced by the shell-escaped name of the previously examined file. However, two consecutive percent signs are simply replaced with a single percent sign. This allows you to enter a filename that contains a percent sign @@ -570,7 +581,7 @@ The setting of the option is not changed. Like the _ (underscore) command, but takes a long option name rather than a single option letter. You must press ENTER or RETURN after typing the option name. -.IP +cmd +.IP +\fIcmd\fP Causes the specified cmd to be executed each time a new file is examined. For example, +G causes .B less @@ -594,11 +605,11 @@ The editor is taken from the environment variable VISUAL if defined, or EDITOR if VISUAL is not defined, or defaults to "vi" if neither VISUAL nor EDITOR is defined. See also the discussion of LESSEDIT under the section on PROMPTS below. -.IP "! shell-command" +.IP "! \fIshell-command\fP" Invokes a shell to run the shell-command given. -A percent sign (%) in the command is replaced by the name of the -current file. -A pound sign (#) is replaced by the name of the previously examined file. +A percent sign (%) in the filename is replaced by the +shell-escaped name of the current file. +A pound sign (#) is replaced by the shell-escaped name of the previously examined file. "!!" repeats the last shell command. "!" with no shell command invokes an interactive shell. If a \*^P (CONTROL-P) is entered immediately after the !, @@ -606,88 +617,85 @@ no "done" message is printed after the shell command is executed. On Unix systems, the shell is taken from the environment variable SHELL, or defaults to "sh". On MS-DOS, Windows, and OS/2 systems, the shell is the normal command processor. -.IP "# shell-command" +.IP "# \fIshell-command\fP" Similar to the "!" command, except that the command is expanded in the same way as prompt strings. For example, the name of the current file would be given as "%f". -.IP "| <m> shell-command" +.IP "| <\fIm\fP> \fIshell-command\fP" <m> represents any mark letter. Pipes a section of the input file to the given shell command. -The section of the file to be piped is between the position marked by -the letter and the current screen. -The entire current screen is included, regardless of whether the -marked position is before or after the current screen. +If the marked line is before the top line of the current screen, +the section to be piped is between the marked line and the bottom line +of the current screen, inclusive. +Otherwise (if the marked line is the top line of the current screen +or after it) the section of the file to be piped is between the top line +of the current screen and the marked line, inclusive. <m> may also be \*^ or $ to indicate beginning or end of file respectively. If <m> is \&.\& or newline, the current screen is piped. If a \*^P (CONTROL-P) is entered immediately after the mark letter, no "done" message is printed after the shell command is executed. -.IP "s filename" +.IP "s \fIfilename\fP" Save the input to a file. This works only if the input is a pipe, not an ordinary file. .IP "\*^O\*^O" .RS Run a shell command to open the URI in the current OSC 8 hyperlink, selected by a previous \*^O\*^N or \*^O\*^P command. -To find the shell command, -the environment variable named "LESS_OSC8_xxx" is read, +The shell command is given by the environment variable +named "LESS_OSC8_OPEN_xxx" where "xxx" is the scheme from the URI (the part before the first colon), -or is empty if there is no colon in the URI. -The value of the environment variable is then expanded in the same way as -prompt strings (in particular, any instance of "%o" is replaced with the URI) -to produce an OSC 8 "handler" shell command. -The standard output from the handler is an "opener" shell command -which is then executed to open the URI. -.PP -There are two special cases: -.RS -.IP 1. -If the URI begins with "#", the remainder of the URI is taken to be -the value of the id parameter in another OSC 8 link in the same file, -and \*^O\*^O will simply jump to that link. -.IP 2. -If the opener begins with the characters ":e" followed by -whitespace and a filename, -then instead of running the opener as a shell command, -the specified filename is opened in the current instance of -.BR less . -.RE +converted to lowercase. +If there is no colon in the URI, the environment variable +LESS_OSC8_OPEN_NONE is used. +The URI from the hyperlink is then shell-escaped and appended to the +value of the environment variable after a space, +and the resulting string is executed as a shell command. .PP -In a simple case where the opener accepts the complete URI -as a command line parameter, the handler may be as simple as +For example, if you wish to open https links by invoking a program +called "mybrowser" with a "\-\-new\-window" option, you could set .PP .EX .nf -echo mybrowser \*'%o\*' +LESS_OSC8_OPEN_https="mybrowser \-\-new\-window" .fi .EE .PP -In other cases, the URI may need to be modified, so the handler -may have to do some manipulation of the %o value. +If the handler command begins with "\-", +the command is not displayed before it is executed. +If the handler command begins with \*^P (CONTROL-P), +the "link done" message is not displayed after it is executed. +If the handler command begins with \*^P followed by "\-", +neither the command nor the "link done" message is displayed. .PP -If the LESS_OSC8_xxx variable is not set, the variable LESS_OSC8_ANY is tried. -If neither LESS_OSC8_xxx nor LESS_OSC8_ANY is set, -links using the "xxx" scheme cannot be opened. -However, there are default handlers for the -schemes "man" (used when LESS_OSC8_man is not set) -and "file" (used when LESS_OSC8_file is not set), -which should work on systems which provide the -.BR sed (1) -command and a shell with syntax compatible with the Bourne shell -.BR sh (1). -If you use LESS_OSC8_ANY to override LESS_OSC8_file, you must -set LESS_OSC8_file to "\-" to indicate that the default value -should not be used, and likewise for LESS_OSC8_man. +If you attempt to open a link with the "xxx" scheme and the +LESS_OSC8_OPEN_xxx variable is not set, +the variable LESS_OSC8_OPEN_ANY is tried. +If neither LESS_OSC8_OPEN_xxx nor LESS_OSC8_OPEN_ANY is set, +links using the "xxx" scheme cannot be opened. +However, there is a default value for LESS_OSC8_OPEN_ANY +which invokes the program +.BR less\-osc8\-open (1). +This program will open links with the +schemes "man" (by running +.BR man (1)) +or "file" (by running another instance of +.BR less (1) +if the file is local). +.B less\-osc8\-open +should work on systems which provide a POSIX-compatible shell. .PP -The URI passed to an OSC8 handler via %o is guaranteed not to contain any single quote -or double quote characters, but it may contain any other shell metacharacters -such as semicolons, dollar signs, ampersands, etc. -The handler should take care to appropriately quote parameters in the opener command, -to prevent execution of unintended shell commands in the case of opening +Any shell metacharacters such as semicolons, dollar signs, ampersands, etc. +in the URI will be shell-escaped before the URI is appended to the handler command. +If the handler passes the URI or any substring of it to a shell, +it should take care to appropriately quote such strings, +to prevent execution of unintended shell commands when opening a URI which contains shell metacharacters. -Also, since the handler command is expanded like a command prompt, -any metacharacters interpreted by prompt expansion -(such as percent, dot, colon, backslash, etc.) must be escaped with a backslash -(see the PROMPTS section for details). +.PP +As a special case, if the URI begins with "#", +the remainder of the URI is taken to be +the value of the id parameter in another OSC 8 link in the same file, +and \*^O\*^O will simply jump to that link rather than running +a handler program. .RE .IP "\*^X" When the "Waiting for data" message is displayed, @@ -816,7 +824,7 @@ the bottom of the screen and backward searches to start at the top of the screen, thus skipping all lines displayed on the screen. .IP "\fB\-A\fP or \fB\-\-SEARCH\-SKIP\-SCREEN\fP" -Causes all forward searches (not just non-repeated searches) +auses all forward searches (not just non-repeated searches) to start just after the target line, and all backward searches to start just before the target line. Thus, forward searches will skip part of the displayed screen @@ -893,6 +901,8 @@ Errors and informational messages. Header lines and columns, set via the .B "\-\-header" option. +.IP "J" +Target line when highlighted via \-\-hilite\-target. .IP "M" Mark letters in the status column. .IP "N" @@ -905,6 +915,9 @@ Prompts. The rscroll character. .IP "S" Search results. +.IP "T" +The tilde lines displayed after the end of the file or +before the beginning of the file. .IP "W" The highlight enabled via the .B "\-w" @@ -1001,7 +1014,7 @@ the corresponding color is set to that of normal text. .PP A 4-bit or 8-bit color string may be followed by one or more of the following characters to set text attributes in addition to the color. -.IP "s or ~" +.IP "s or \*~" Standout (reverse video) .IP "u or _" Underline @@ -1247,7 +1260,7 @@ Warning: certain environment variables such as LESS, LESSSECURE, LESSCHARSET and others, which are used early in startup, cannot be set in a file specified by a command line option -.RB "(" "\-\-lesskey" "," "\-\-lesskey\-src" " or " "\-\-lesskey\-content" ")." +.RB "(" "\-\-lesskey" ", " "\-\-lesskey\-src" " or " "\-\-lesskey\-content" ")." When using a .B lesskey file to set environment variables, it is safer to use the @@ -1560,7 +1573,7 @@ options. Displays the version number of .BR less . .IP "\fB\-w\fP or \fB\-\-hilite\-unread\fP" -Temporarily highlights the first "new" line after a forward movement +Temporarily highlights the first "new" line after a movement of a full page. The first "new" line is the line immediately following the line previously at the bottom of the screen. @@ -1579,16 +1592,22 @@ in which case only the status column is highlighted. Like .BR "\-w" "," but temporarily highlights the first new line after any -forward movement command larger than one line. +movement command larger than one line. .IP "\fB\-x\fP\fIn\fP,...\& or \fB\-\-tabs=\fP\fIn\fP,..." Sets tab stops. If only one \fIn\fP is specified, tab stops are set at multiples of \fIn\fP. If multiple values separated by commas are specified, tab stops are set at those positions, and then continue with the same spacing as the last two. +Position numbers are zero-based: the leftmost position is 0, +the next is 1, etc. For example, -.RB "\[dq]" "\-x9,17" "\[dq]" -will set tabs at positions 9, 17, 25, 33, etc. +.RB "\[dq]" "\-x8,16" "\[dq]" +is the same as +.RB "\[dq]" "\-x8" "\[dq]" +and sets tabs at position 8, 16, 24, 32, etc. +.RB "\[dq]" "\-x10,14,20" "\[dq]" +will set tabs at position 10, 14, 20, 26, 32, etc. The default for \fIn\fP is 8. .IP "\fB\-X\fP or \fB\-\-no\-init\fP" Disables sending the termcap initialization and deinitialization strings @@ -1693,6 +1712,76 @@ option, while commands specified by the \fB+\fP option are executed even if .B less exits immediately. +.IP "\fB\-\-emouse=\fP\fIfeatures\fP +\fIfeatures\fP is a comma-separated list of mouse features to be enabled, +selected from this list: +.RS +.IP "vscroll" +Scrolling the mouse wheel down or up moves forward or backward in +the file. +The number of lines to scroll when the wheel is moved can be set by the +.B "\-\-wheel\-lines" +option. +The +.B "\-\-rmouse" +option reverses the direction of movement. +.IP "vdrag" +Holding down the left button and dragging up or down moves +forward or backward in the file. +.IP "hscroll" +Scrolling the side scroll wheel left or right moves left or right +in the file. +The number of columns to scroll when the wheel is moved can be set by the +.B "\-\-wheel\-lines" +option. +The +.B "\-\-rmouse" +option reverses the direction of movement. +.IP "hdrag" +Holding down the left button and dragging left or right moves +left or right in the file. +.IP "lclick" +Left-clicking sets the "#" mark to the line where the mouse is clicked. +If a left-click is performed with the mouse cursor on an OSC 8 hyperlink, +the hyperlink is selected as if by the \*^O\*^N command. +If a left-click is performed with the mouse cursor on an OSC 8 hyperlink +which is already selected, the hyperlink is opened as if by the \*^O\*^O command. +.IP "rclick" +Right-clicking (or clicking any button other than the left one) +returns to the "#" mark position. +.IP "scroll" +Same as "vscroll,hscroll". +.IP "drag" +Same as "vdrag,hdrag". +.IP "hmove" +Same as "hscroll,hdrag". +.IP "vmove" +Same as "vscroll,vdrag". +.IP "move" +Same as "vmove,hmove". +.IP "click" +Same as "lclick,rclick". +.IP "all" +Same as "move,click". +.RE +.IP +Each feature name may be abbreviated as long as the abbreviation +is unambiguous. +If \fIfeatures\fP is set to "-", all mouse features are disabled. +Mouse input works only on terminals which support X11 mouse reporting, +and on Windows. +.IP "\fB\-\-end\-prompt=\fP\fIstring\fP" +Specifies a string which is printed immediately after the prompt is erased. +As with the \fB\-\-prompt\fP option, the first character of the string +determines which prompt the string will be printed after +("\fBs\fP" for the short prompt, "\fBm\fP" for the medium prompt, +or "\fBM\fP" for the long prompt). +Special characters in the string are processed as described in the PROMPTS +section, in the same way as prompts specified by the \fB\-\-prompt\fP option. +If set to a dash (\fB\-\fP), nothing is printed after the prompt is erased. +This option can be useful if the prompt string has been modified to contain +an escape sequence that puts the terminal in a mode which should be cleared +when the prompt is erased. .IP "\fB\-\-exit\-follow\-on\-close\fP" When using the "F" command on a pipe, .B less @@ -1705,7 +1794,8 @@ is specified, .B less will determine the size of the file immediately after opening the file. -Then the "=" command will display the number of lines in the file. +With this option enabled, the = command and the long prompt will display +the number of lines in the file. Normally this is not done, because it can be slow if the input file is non-seekable (such as a pipe) and is large. .IP "\fB\-\-follow\-name\fP" @@ -1768,6 +1858,17 @@ and the .B "\-S" option is ignored. .RE +.IP "\fB\-\-hilite\-target\fP" +Highlights the "target" line, as specified by the \-j option. +If the +.B "\-\-status\-line" +option is in effect, the entire line +(the width of the screen) is highlighted. +Otherwise, only the text in the line is highlighted, +unless the +.B "\-J" +option is in effect, +in which case only the status column is highlighted. .IP "\fB\-\-incsearch\fP" Subsequent search commands will be "incremental"; that is, .B less @@ -1833,27 +1934,13 @@ See the description for acceptable values of \fIn\fP. .RE .IP "\fB\-\-mouse\fP" -Enables mouse input: -scrolling the mouse wheel down moves forward in the file, -scrolling the mouse wheel up moves backwards in the file, -left-click sets the "#" mark to the line where the mouse is clicked, -and right-click (or any other) returns to the "#" mark position. -Holding down the left button and dragging also moves in the file. -If a left-click is performed with the mouse cursor on an OSC 8 hyperlink, -the hyperlink is selected as if by the \*^O\*^N command. -If a left-click is performed with the mouse cursor on an OSC 8 hyperlink -which is already selected, the hyperlink is opened as if by the \*^O\*^O command. -The number of lines to scroll when the wheel is moved -can be set by the -.B "\-\-wheel\-lines" -option. -Mouse input works only on terminals which support X11 mouse reporting, -and on Windows. +Enabling \fB\-\-mouse\fP is the same as \fB\-\-emouse=vmove,click\fP. +Disabling \fB\-\-mouse\fP is the same as \fB\-\-emouse=-\fP. .IP "\fB\-\-MOUSE\fP" Like -.BR "\-\-mouse" "," -except the direction scrolled -on mouse wheel movement is reversed. +.B "\-\-mouse" +with +.BR "\-\-rmouse" "." .IP "\fB\-\-no\-edit\-warn\fP" Don't print a warning message when using the v command on a file which was opened using a LESSOPEN preprocessor @@ -1891,6 +1978,12 @@ Searches do not include header columns, but still include header lines. Searches do not include header lines or header columns. .IP "\fB\-\-no\-vbell\fP" Disables the terminal's visual bell. +.IP "\fB\-\-past\-eof\fP" +Normally scrolling commands (other than J, K, ESC-SPACE and ESC-b) +stop scrolling when end-of-file is reached scrolling forward, or +beginning-of-file is reached scrolling backward. +This option makes all scrolling commands continue past end-of-file +or beginning-of-file. .IP "\fB\-\-proc\-backspace\fP" If set, backspaces are handled as if neither the .B "\-u" @@ -1966,6 +2059,9 @@ terminal to switch from an alternate screen, this makes the last screenful of the current file remain visible after .B less has quit. +.IP "\fB\-\-rmouse\fP" +Reverses the normal direction of scrolling when mouse scrolling is +enabled via \fB\-\-emouse=vscroll\fP or \fB\-\-emouse=hscroll\fP. .IP "\fB\-\-rscroll=\fP\fIc\fP" This option changes the character used to mark truncated lines. It may begin with a two-character attribute indicator like LESSBINFMT does. @@ -2004,6 +2100,8 @@ If a line is marked, the entire line (rather than just the status column) is highlighted. Also lines highlighted due to the .B "\-w" +or +.B "\-\-hilite\-target" option will have the entire line highlighted. If @@ -2027,13 +2125,13 @@ ANSI color escape sequences (as defined in https://\*:www\*:.ecma\-international\*:.org/\*:publications\-and\-standards/\*:standards/\*:ecma\-48). .hy .IP "\fB\-\-wheel\-lines=\fP\fIn\fP" -Set the number of lines to scroll when the mouse wheel is scrolled +Set the number of lines or columns to scroll when the mouse wheel is scrolled and the .B "\-\-mouse" or .B "\-\-MOUSE" option is in effect. -The default is 1 line. +The default is 1 line or column. .IP "\fB\-\-wordwrap\fP" When the .B "\-S" @@ -2098,7 +2196,7 @@ Move the cursor to the end of the line. .IP "BACKSPACE" Delete the character to the left of the cursor, or cancel the command if the command line is empty. -.IP "DELETE or [ ESC-x ]" +.IP "DELETE [ ESC-x ]" Delete the character under the cursor. .IP "\*^BACKSPACE [ ESC-BACKSPACE ]" (That is, CONTROL and BACKSPACE simultaneously.) @@ -2118,13 +2216,13 @@ it will retrieve the next command which begins with that text. Complete the partial filename to the left of the cursor. If it matches more than one filename, the first match is entered into the command line. -Repeated TABs will cycle thru the other matching filenames. +Repeated TABs will cycle through the other matching filenames. If the completed filename is a directory, a "/" is appended to the filename. (On MS-DOS and Windows systems, a "\e" is appended.) The environment variable LESSSEPARATOR can be used to specify a different character to append to a directory name. .IP "BACKTAB (SHIFT-TAB) [ ESC-TAB ]" -Like TAB, but cycles in the reverse direction thru the matching filenames. +Like TAB, but cycles in the reverse direction through the matching filenames. .IP "\*^L" Complete the partial filename to the left of the cursor. If it matches more than one filename, all matches are entered into @@ -2355,14 +2453,14 @@ For compatibility with previous versions of the input preprocessor or pipe is not used if .B less is viewing standard input. -However, if the first character of LESSOPEN is a dash (\-), +However, if the first character of LESSOPEN is a dash (\fB\-\fP), the input preprocessor is used on standard input as well as other files. In this case, the dash is not considered to be part of the preprocessor command. If standard input is being viewed, the input preprocessor is passed a file name consisting of a single dash. Similarly, if the first two characters of LESSOPEN are vertical bar and dash -(|\-) or two vertical bars and a dash (||\-), +(\fB|\-\fP) or two vertical bars and a dash (\fB||\-\fP), the input pipe is used on standard input as well as other files. Again, in this case the dash is not considered to be part of the input pipe command. @@ -2627,10 +2725,6 @@ The line to be used is determined by the \fIX\fP, as with the %b option. Replaced by the line number of the last line in the input file. .IP "%m" Replaced by the total number of input files. -.IP "%o" -Replaced by the URI of the currently selected OSC 8 hyperlink, -or a question mark if no hyperlink is selected. -This is used by OSC 8 handlers as explained in the \*^O\*^O command description. .IP "%p\fIX\fP" Replaced by the percent into the current input file, based on byte offsets. The line used is determined by the \fIX\fP as with the %b option. @@ -2681,7 +2775,7 @@ True if the byte offset of the specified line is known. .IP "?B" True if the size of current input file is known. .IP "?c" -True if the text is horizontally shifted (%c is not zero). +True if the text is horizontally shifted (%c is greater than 1). .IP "?d\fIX\fP" True if the page number of the specified line is known. .IP "?e" @@ -2697,6 +2791,8 @@ True if the line number of the last line in the file is known. True if there is more than one input file. .IP "?n" True if this is the first prompt in a new input file. +.IP "?O" +True if an OSC 8 hyperlink is selected. .IP "?p\fIX\fP" True if the percent into the current input file, based on byte offsets, of the specified line is known. @@ -3085,12 +3181,15 @@ The default is 4000 (4 seconds). Emulate the .BR more (1) command. -.IP LESS_OSC8_xxx +.IP LESS_OSC8_OPEN_xxx Where "xxx" is a URI scheme such as "http" or "file", sets an OSC 8 handler for opening OSC 8 links containing a URI with that scheme. -.IP LESS_OSC8_ANY +.IP LESS_OSC8_OPEN_ANY Sets an OSC 8 handler for opening OSC 8 links for which there is -no specific LESS_OSC8_xxx handler set for the "xxx" scheme. +no specific LESS_OSC8_OPEN_xxx handler set for the "xxx" scheme. +.IP LESS_OSC8_OPEN_NONE +Sets an OSC 8 handler for opening OSC 8 links which contain no scheme +(that is, there is no colon in the URI). .IP LESS_SHELL_LINES When the .B "\-F" diff --git a/lessecho.man b/lessecho.man index 5d6bfcb1b323..58b473673748 100644 --- a/lessecho.man +++ b/lessecho.man @@ -52,4 +52,4 @@ Report bugs at https://github.com/gwsw/less/issues. -less 692 29 Jan 2026 [4mLESSECHO[24m(1) +less 704 30 May 2026 [4mLESSECHO[24m(1) diff --git a/lessecho.nro b/lessecho.nro index c860dd847405..d7bb81a300ed 100644 --- a/lessecho.nro +++ b/lessecho.nro @@ -1,4 +1,4 @@ -.TH LESSECHO 1 "29 Jan 2026" "less 692" +.TH LESSECHO 1 "30 May 2026" "less 704" .\" Define a string to interpolate the hyphenless break point escape .\" sequence (for URLs and similar) if the formatter claims groff .\" compatibility, else interpolate nothing. diff --git a/lesskey.man b/lesskey.man index 409bda26b3b6..fab96d5229d8 100644 --- a/lesskey.man +++ b/lesskey.man @@ -104,6 +104,7 @@ \kp+ + on the numeric keypad \kp. . on the numeric keypad \kp, , on the numeric keypad + \kpe ENTER on the numeric keypad A backslash followed by any other character indicates that character is to be taken literally. Characters which must be preceded by backslash @@ -480,4 +481,4 @@ Mark Nudelman Report bugs at https://github.com/gwsw/less/issues. -less 692 29 Jan 2026 [4mLESSKEY[24m(1) +less 704 30 May 2026 [4mLESSKEY[24m(1) diff --git a/lesskey.nro b/lesskey.nro index 11f5a306aea8..e472a059ce87 100644 --- a/lesskey.nro +++ b/lesskey.nro @@ -1,5 +1,5 @@ '\" t -.TH LESSKEY 1 "29 Jan 2026" "less 692" +.TH LESSKEY 1 "30 May 2026" "less 704" .\" Define a string for the caret ("hat") as portably as possible. .ie \n(.g .ds ^ \(ha .el .ds ^ ^ @@ -148,6 +148,7 @@ l l. \ekp+ + on the numeric keypad \ekp. . on the numeric keypad \ekp, , on the numeric keypad +\ekpe ENTER on the numeric keypad .TE .RE .PP diff --git a/lesskey_parse.c b/lesskey_parse.c index d19ae26dffdf..d69b0cd7d0fd 100644 --- a/lesskey_parse.c +++ b/lesskey_parse.c @@ -128,6 +128,7 @@ static constant struct lesskey_cmdname editnames[] = { "literal", EC_LITERAL }, { "mouse", EC_X11MOUSE }, { "mouse6", EC_X116MOUSE }, + { "noaction", A_NOACTION }, { "right", EC_RIGHT }, { "up", EC_UP }, { "word-backspace", EC_W_BACKSPACE }, @@ -295,6 +296,7 @@ static constant char * tstr(char **pp, int xlate) case '+': ch = SK_PAD_PLUS; break; case '.': ch = SK_PAD_DOT; break; case ',': ch = SK_PAD_COMMA; break; + case 'e': ch = SK_PAD_ENTER; break; } break; } diff --git a/lesstest/lt/filter1.lt b/lesstest/lt/filter1.lt index 2a621cac1077..dc0a5ad5f04c 100644 --- a/lesstest/lt/filter1.lt +++ b/lesstest/lt/filter1.lt @@ -1,6 +1,6 @@ !lesstest! !version 1 -!created 2025-04-27 17:39:44 +!created 2026-02-15 17:57:19 E "LESS_TERMCAP_am" "1" E "LESS_TERMCAP_cd" "S" E "LESS_TERMCAP_ce" "L" @@ -27,6 +27,8 @@ E "LESS_TERMCAP_@7" "OF" E "COLUMNS" "79" E "LINES" "34" E "LANG" "C" +E "LESSCHARSET" "" +E "LESS" "" E "LC_CTYPE" "en_US.UTF-8" T "filter1" A "filter1" @@ -1086,7 +1088,7 @@ R +4e =@04*@00 3@045@00___________________________________________________________________________ 36___________________________________________________________________________ 37___________________________________________________________________________ 38___________________________________________________________________________ 39___________________________________________________________________________ 43___________________________________________________________________________@04*@00 @045@003___________________________________________________________________________ 63___________________________________________________________________________ 73___________________________________________________________________________ 83___________________________________________________________________________ 93___________________________________________________________________________ 103__________________________________________________________________________ 113__________________________________________________________________________ 123__________________________________________________________________________ 130__________________________________________________________________________ 131__________________________________________________________________________ 132__________________________________________________________________________ 133__________________________________________________________________________ 134__________________________________________________________________________@04*@00 13@045@00__________________________________________________________________________ 136__________________________________________________________________________ 137__________________________________________________________________________ 138__________________________________________________________________________ 139__________________________________________________________________________ 143__________________________________________________________________________@04*@00 1@045@003__________________________________________________________________________ 163__________________________________________________________________________ 173__________________________________________________________________________ 183__________________________________________________________________________ 193__________________________________________________________________________ 203__________________________________________________________________________ 213__________________________________________________________________________ 223__________________________________________________________________________& :#____________________________________________________________________________ +4e -=@04*@00 3@045@00___________________________________________________________________________ 36___________________________________________________________________________ 37___________________________________________________________________________ 38___________________________________________________________________________ 39___________________________________________________________________________ 43___________________________________________________________________________@04*@00 @045@003___________________________________________________________________________ 63___________________________________________________________________________ 73___________________________________________________________________________ 83___________________________________________________________________________ 93___________________________________________________________________________ 103__________________________________________________________________________ 113__________________________________________________________________________ 123__________________________________________________________________________ 130__________________________________________________________________________ 131__________________________________________________________________________ 132__________________________________________________________________________ 133__________________________________________________________________________ 134__________________________________________________________________________@04*@00 13@045@00__________________________________________________________________________ 136__________________________________________________________________________ 137__________________________________________________________________________ 138__________________________________________________________________________ 139__________________________________________________________________________ 143__________________________________________________________________________@04*@00 1@045@003__________________________________________________________________________ 163__________________________________________________________________________ 173__________________________________________________________________________ 183__________________________________________________________________________ 193__________________________________________________________________________ 203__________________________________________________________________________ 213__________________________________________________________________________ 223__________________________________________________________________________@04Pattern not found (press RETURN)@00#______________________________________________ +=@04*@00 3@045@00___________________________________________________________________________ 36___________________________________________________________________________ 37___________________________________________________________________________ 38___________________________________________________________________________ 39___________________________________________________________________________ 43___________________________________________________________________________@04*@00 @045@003___________________________________________________________________________ 63___________________________________________________________________________ 73___________________________________________________________________________ 83___________________________________________________________________________ 93___________________________________________________________________________ 103__________________________________________________________________________ 113__________________________________________________________________________ 123__________________________________________________________________________ 130__________________________________________________________________________ 131__________________________________________________________________________ 132__________________________________________________________________________ 133__________________________________________________________________________ 134__________________________________________________________________________@04*@00 13@045@00__________________________________________________________________________ 136__________________________________________________________________________ 137__________________________________________________________________________ 138__________________________________________________________________________ 139__________________________________________________________________________ 143__________________________________________________________________________@04*@00 1@045@003__________________________________________________________________________ 163__________________________________________________________________________ 173__________________________________________________________________________ 183__________________________________________________________________________ 193__________________________________________________________________________ 203__________________________________________________________________________ 213__________________________________________________________________________ 223__________________________________________________________________________@04Pattern not found: 5 (press RETURN)@00#___________________________________________ +26 =@04*@00 3@045@00___________________________________________________________________________ 36___________________________________________________________________________ 37___________________________________________________________________________ 38___________________________________________________________________________ 39___________________________________________________________________________ 43___________________________________________________________________________@04*@00 @045@003___________________________________________________________________________ 63___________________________________________________________________________ 73___________________________________________________________________________ 83___________________________________________________________________________ 93___________________________________________________________________________ 103__________________________________________________________________________ 113__________________________________________________________________________ 123__________________________________________________________________________ 130__________________________________________________________________________ 131__________________________________________________________________________ 132__________________________________________________________________________ 133__________________________________________________________________________ 134__________________________________________________________________________@04*@00 13@045@00__________________________________________________________________________ 136__________________________________________________________________________ 137__________________________________________________________________________ 138__________________________________________________________________________ 139__________________________________________________________________________ 143__________________________________________________________________________@04*@00 1@045@003__________________________________________________________________________ 163__________________________________________________________________________ 173__________________________________________________________________________ 183__________________________________________________________________________ 193__________________________________________________________________________ 203__________________________________________________________________________ 213__________________________________________________________________________ 223__________________________________________________________________________&/#_____________________________________________________________________________ +a @@ -1146,7 +1148,7 @@ R +4e =@04*@00 @045@006___________________________________________________________________________ 60___________________________________________________________________________ 61___________________________________________________________________________ 62___________________________________________________________________________ 63___________________________________________________________________________ 64___________________________________________________________________________@04*@00 6@045@00___________________________________________________________________________ 66___________________________________________________________________________ 67___________________________________________________________________________ 68___________________________________________________________________________ 69___________________________________________________________________________ 76___________________________________________________________________________ 86___________________________________________________________________________ 96___________________________________________________________________________ 106__________________________________________________________________________ 116__________________________________________________________________________ 126__________________________________________________________________________ 136__________________________________________________________________________ 146__________________________________________________________________________@04*@00 1@045@006__________________________________________________________________________ 160__________________________________________________________________________ 161__________________________________________________________________________ 162__________________________________________________________________________ 163__________________________________________________________________________ 164__________________________________________________________________________@04*@00 16@045@00__________________________________________________________________________ 166__________________________________________________________________________ 167__________________________________________________________________________ 168__________________________________________________________________________ 169__________________________________________________________________________ 176__________________________________________________________________________ 186__________________________________________________________________________ 196__________________________________________________________________________& :#____________________________________________________________________________ +4e -=@04*@00 @045@006___________________________________________________________________________ 60___________________________________________________________________________ 61___________________________________________________________________________ 62___________________________________________________________________________ 63___________________________________________________________________________ 64___________________________________________________________________________@04*@00 6@045@00___________________________________________________________________________ 66___________________________________________________________________________ 67___________________________________________________________________________ 68___________________________________________________________________________ 69___________________________________________________________________________ 76___________________________________________________________________________ 86___________________________________________________________________________ 96___________________________________________________________________________ 106__________________________________________________________________________ 116__________________________________________________________________________ 126__________________________________________________________________________ 136__________________________________________________________________________ 146__________________________________________________________________________@04*@00 1@045@006__________________________________________________________________________ 160__________________________________________________________________________ 161__________________________________________________________________________ 162__________________________________________________________________________ 163__________________________________________________________________________ 164__________________________________________________________________________@04*@00 16@045@00__________________________________________________________________________ 166__________________________________________________________________________ 167__________________________________________________________________________ 168__________________________________________________________________________ 169__________________________________________________________________________ 176__________________________________________________________________________ 186__________________________________________________________________________ 196__________________________________________________________________________@04Pattern not found (press RETURN)@00#______________________________________________ +=@04*@00 @045@006___________________________________________________________________________ 60___________________________________________________________________________ 61___________________________________________________________________________ 62___________________________________________________________________________ 63___________________________________________________________________________ 64___________________________________________________________________________@04*@00 6@045@00___________________________________________________________________________ 66___________________________________________________________________________ 67___________________________________________________________________________ 68___________________________________________________________________________ 69___________________________________________________________________________ 76___________________________________________________________________________ 86___________________________________________________________________________ 96___________________________________________________________________________ 106__________________________________________________________________________ 116__________________________________________________________________________ 126__________________________________________________________________________ 136__________________________________________________________________________ 146__________________________________________________________________________@04*@00 1@045@006__________________________________________________________________________ 160__________________________________________________________________________ 161__________________________________________________________________________ 162__________________________________________________________________________ 163__________________________________________________________________________ 164__________________________________________________________________________@04*@00 16@045@00__________________________________________________________________________ 166__________________________________________________________________________ 167__________________________________________________________________________ 168__________________________________________________________________________ 169__________________________________________________________________________ 176__________________________________________________________________________ 186__________________________________________________________________________ 196__________________________________________________________________________@04Pattern not found: 5 (press RETURN)@00#___________________________________________ +47 =@04*@00 8@045@006__________________________________________________________________________ 860__________________________________________________________________________ 861__________________________________________________________________________ 862__________________________________________________________________________ 863__________________________________________________________________________ 864__________________________________________________________________________@04*@00 86@045@00__________________________________________________________________________ 866__________________________________________________________________________ 867__________________________________________________________________________ 868__________________________________________________________________________ 869__________________________________________________________________________ 876__________________________________________________________________________ 886__________________________________________________________________________ 896__________________________________________________________________________ 906__________________________________________________________________________ 916__________________________________________________________________________ 926__________________________________________________________________________ 936__________________________________________________________________________ 946__________________________________________________________________________@04*@00 9@045@006__________________________________________________________________________ 960__________________________________________________________________________ 961__________________________________________________________________________ 962__________________________________________________________________________ 963__________________________________________________________________________ 964__________________________________________________________________________@04*@00 96@045@00__________________________________________________________________________ 966__________________________________________________________________________ 967__________________________________________________________________________ 968__________________________________________________________________________ 969__________________________________________________________________________ 976__________________________________________________________________________ 986__________________________________________________________________________ 996__________________________________________________________________________& :#____________________________________________________________________________ +6e @@ -1156,7 +1158,7 @@ R +6e =@04*@00 96@045@00__________________________________________________________________________ 966__________________________________________________________________________ 967__________________________________________________________________________ 968__________________________________________________________________________ 969__________________________________________________________________________ 976__________________________________________________________________________ 986__________________________________________________________________________ 996__________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________& @04(END)@00#________________________________________________________________________ +6e -=@04*@00 96@045@00__________________________________________________________________________ 966__________________________________________________________________________ 967__________________________________________________________________________ 968__________________________________________________________________________ 969__________________________________________________________________________ 976__________________________________________________________________________ 986__________________________________________________________________________ 996__________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@04Pattern not found (press RETURN)@00#______________________________________________ +=@04*@00 96@045@00__________________________________________________________________________ 966__________________________________________________________________________ 967__________________________________________________________________________ 968__________________________________________________________________________ 969__________________________________________________________________________ 976__________________________________________________________________________ 986__________________________________________________________________________ 996__________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@04Pattern not found: 5 (press RETURN)@00#___________________________________________ +a =@04*@00 96@045@00__________________________________________________________________________ 966__________________________________________________________________________ 967__________________________________________________________________________ 968__________________________________________________________________________ 969__________________________________________________________________________ 976__________________________________________________________________________ 986__________________________________________________________________________ 996__________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________@01~@00______________________________________________________________________________& @04(END)@00#________________________________________________________________________ +26 diff --git a/lesstest/lt/search-hist.lt b/lesstest/lt/search-hist.lt index e67d914d8e25..166538df808e 100644 --- a/lesstest/lt/search-hist.lt +++ b/lesstest/lt/search-hist.lt @@ -1,6 +1,6 @@ !lesstest! !version 1 -!created 2025-07-29 05:50:23 +!created 2026-02-15 17:57:18 E "LESS_TERMCAP_am" "1" E "LESS_TERMCAP_cd" "S" E "LESS_TERMCAP_ce" "L" @@ -27,6 +27,8 @@ E "LESS_TERMCAP_@7" "OF" E "COLUMNS" "103" E "LINES" "34" E "LANG" "C" +E "LESSCHARSET" "" +E "LESS" "" E "LC_CTYPE" "en_US.UTF-8" T "search-hist" A "search-hist" @@ -178,7 +180,7 @@ R +41 =@04te@00n____________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________/five#__________________________________________________________________________________________________ +a -=ten____________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@04Pattern not found (press RETURN)@00#______________________________________________________________________ +=ten____________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@04Pattern not found: five (press RETURN)@00#________________________________________________________________ +67 =one____________________________________________________________________________________________________two____________________________________________________________________________________________________three__________________________________________________________________________________________________four___________________________________________________________________________________________________@04five@00___________________________________________________________________________________________________six____________________________________________________________________________________________________seven__________________________________________________________________________________________________eight__________________________________________________________________________________________________nine___________________________________________________________________________________________________ten____________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@01~@00______________________________________________________________________________________________________@04(END)@00#__________________________________________________________________________________________________ +2d @@ -135,6 +135,8 @@ static struct color_map color_map[] = { { AT_COLOR_RSCROLL, "kc" }, { AT_COLOR_HEADER, "" }, { AT_COLOR_SEARCH, "kG" }, + { AT_COLOR_TILDE, "-d" }, + { AT_COLOR_TARGET, "-u" }, { AT_COLOR_SUBSEARCH(1), "ky" }, { AT_COLOR_SUBSEARCH(2), "wb" }, { AT_COLOR_SUBSEARCH(3), "YM" }, @@ -446,7 +448,7 @@ public void plinestart(POSITION pos) * Return the width of the line prefix (status column and line number). * {{ Actual line number can be wider than linenum_width. }} */ -public int line_pfx_width(void) +public unsigned line_pfx_width(void) { int width = 0; if (status_col) @@ -1077,7 +1079,7 @@ static int flush_mbc_buf(POSITION pos) */ public int pappend_b(char c, POSITION pos, lbool before_pendc) { - LWCHAR ch = c & 0377; + LWCHAR ch = (unsigned char) c; int r; if (pendc && !before_pendc) @@ -1192,6 +1194,22 @@ static int store_control_char(LWCHAR ch, constant char *rep, POSITION pos) return (0); } +/* + * Remove invalid ANSI sequence. + */ +static void remove_ansi(void) +{ + constant char *start = (cshift < hshift) ? xbuf_char_data(&shifted_ansi): linebuf.buf; + size_t *end = (cshift < hshift) ? &shifted_ansi.end : &linebuf.end; + constant char *p = start + *end; + LWCHAR bch; + do { + bch = step_charc(&p, -1, start); + } while (p > start && (!IS_CSI_START(bch) || line_ansi->escs_in_seq-- > 0)); + *end = ptr_diff(p, start); + xbuf_reset(&last_ansi); +} + static int store_ansi(LWCHAR ch, constant char *rep, POSITION pos) { switch (ansi_step2(line_ansi, ch, pos != NULL_POSITION)) @@ -1215,18 +1233,7 @@ static int store_ansi(LWCHAR ch, constant char *rep, POSITION pos) curr_last_ansi = (curr_last_ansi + 1) % NUM_LAST_ANSIS; break; case ANSI_ERR: - { - /* Remove whole unrecognized sequence. */ - constant char *start = (cshift < hshift) ? xbuf_char_data(&shifted_ansi): linebuf.buf; - size_t *end = (cshift < hshift) ? &shifted_ansi.end : &linebuf.end; - constant char *p = start + *end; - LWCHAR bch; - do { - bch = step_charc(&p, -1, start); - } while (p > start && (!IS_CSI_START(bch) || line_ansi->escs_in_seq-- > 0)); - *end = ptr_diff(p, start); - } - xbuf_reset(&last_ansi); + remove_ansi(); ansi_done(line_ansi); line_ansi = NULL; break; @@ -1388,13 +1395,12 @@ static void add_attr_normal(void) { switch (line_ansi->ostate) { - case OSC_TYPENUM: - case OSC8_PARAMS: - case OSC8_URI: - case OSC_STRING: - addstr_linebuf("\033\\", AT_ANSI, 0); + case OSC_START: + case OSC_END: break; default: + /* We're in an unterminated OSC sequence; remove it. */ + remove_ansi(); break; } ansi_done(line_ansi); @@ -1410,7 +1416,7 @@ static void add_attr_normal(void) /* * Terminate the line in the line buffer. */ -public void pdone(lbool endline, lbool chopped, lbool forw) +public void pdone(lbool endline, lbool chopped, lbool forw, lbool full_pad) { (void) pflushmbc(); linebuf.prev_end = (!endline && !chopped) ? linebuf.end : 0; @@ -1462,8 +1468,8 @@ public void pdone(lbool endline, lbool chopped, lbool forw) /* * If we're coloring a status line, fill out the line with spaces. */ - if (status_line && line_mark_attr != 0) { - while (end_column +1 < sc_width + cshift) + if (status_line && (line_mark_attr != 0 || full_pad)) { + while (end_column < sc_width + cshift) add_linebuf(' ', line_mark_attr, 1); } @@ -1664,7 +1670,7 @@ public int gline(size_t i, int *ap) { if (i == 0) { - *ap = AT_BOLD; + *ap = use_color ? AT_COLOR_TILDE : AT_BOLD; return '~'; } --i; @@ -1681,7 +1687,7 @@ public int gline(size_t i, int *ap) } i += linebuf.print - linebuf.pfx_end; *ap = linebuf.attr[i]; - return (linebuf.buf[i] & 0xFF); + return (unsigned char) linebuf.buf[i]; } /* @@ -1878,10 +1884,10 @@ static int pappstr(constant char *str) /* * Load a string into the line buffer. - * If the string is too long to fit on the screen, + * If the string is too long to fit on the screen (minus reserve chars), * truncate the beginning of the string to fit. */ -public void load_line(constant char *str) +public void load_line(constant char *str, int attr, int reserve) { int save_hshift = hshift; hshift = 0; @@ -1889,6 +1895,7 @@ public void load_line(constant char *str) /* We're overwriting the line buffer, so what's in it will no longer be contiguous. */ set_line_contig_pos(NULL_POSITION); + sc_width -= reserve; for (;;) { prewind(FALSE); @@ -1903,13 +1910,14 @@ public void load_line(constant char *str) } set_linebuf(linebuf.end, '\0', AT_NORMAL); linebuf.prev_end = 0; + sc_width += reserve; /* Color the prompt unless it has ansi sequences in it. */ if (!ansi_in_line) { size_t i; for (i = linebuf.print; i < linebuf.end; i++) - set_linebuf(i, linebuf.buf[i], AT_STANDOUT|AT_COLOR_PROMPT); + set_linebuf(i, linebuf.buf[i], attr); } hshift = save_hshift; } diff --git a/lsystem.c b/lsystem.c index 63c0cf074524..40bff05954e2 100644 --- a/lsystem.c +++ b/lsystem.c @@ -266,7 +266,7 @@ public int pipe_mark(char c, constant char *cmd) if (c == '.') return (pipe_data(cmd, tpos, bpos)); - else if (mpos <= tpos) + else if (mpos < tpos) return (pipe_data(cmd, mpos, bpos)); else if (bpos == NULL_POSITION) return (pipe_data(cmd, tpos, bpos)); @@ -29,7 +29,7 @@ public unsigned less_acp = CP_ACP; public char * every_first_cmd = NULL; public lbool new_file; -public int is_tty; +public lbool is_tty; public IFILE curr_ifile = NULL_IFILE; public IFILE old_ifile = NULL_IFILE; public struct scrpos initial_scrpos; @@ -38,7 +38,7 @@ public POSITION end_attnpos = NULL_POSITION; public int wscroll; public constant char *progname; public lbool quitting = FALSE; -public int dohelp; +public lbool dohelp = FALSE; public char * init_header = NULL; public char * no_config = NULL; static int secure_allow_features; @@ -68,7 +68,7 @@ public time_type less_start_time; static wchar_t consoleTitle[256]; #endif -public int one_screen; +public lbool one_screen; extern int less_is_more; extern lbool missing_cap; extern int know_dumb; @@ -158,26 +158,16 @@ cleanup: } #endif -#if !SECURE -static int security_feature_error(constant char *type, size_t len, constant char *name) -{ - PARG parg; - size_t msglen = len + strlen(type) + 64; - char *msg = ecalloc(msglen, sizeof(char)); - SNPRINTF3(msg, msglen, "LESSSECURE_ALLOW: %s feature name \"%.*s\"", type, (int) len, name); - parg.p_string = msg; - error("%s", &parg); - free(msg); - return 0; -} - /* - * Return the SF_xxx value of a secure feature given the name of the feature. + * Set the secure_allow_features bitmask, which controls + * whether certain secure features are allowed. */ -static int security_feature(constant char *name, size_t len) +static void init_secure(void) { - struct secure_feature { constant char *name; int sf_value; }; - static struct secure_feature features[] = { +#if SECURE + secure_allow_features = 0; +#else + static struct csl_bitmap_def security_features[] = { { "edit", SF_EDIT }, { "examine", SF_EXAMINE }, { "glob", SF_GLOB }, @@ -191,39 +181,6 @@ static int security_feature(constant char *name, size_t len) { "stop", SF_STOP }, { "tags", SF_TAGS }, }; - int i; - int match = -1; - - for (i = 0; i < countof(features); i++) - { - if (strncmp(features[i].name, name, len) == 0) - { - if (match >= 0) /* name is ambiguous */ - return security_feature_error("ambiguous", len, name); - match = i; - } - } - if (match < 0) - return security_feature_error("invalid", len, name); - return features[match].sf_value; -} - -static lbool set_security_feature(constant char *word, size_t wlen, void *arg) -{ - secure_allow_features |= security_feature(word, wlen); - return TRUE; -} -#endif /* !SECURE */ - -/* - * Set the secure_allow_features bitmask, which controls - * whether certain secure features are allowed. - */ -static void init_secure(void) -{ -#if SECURE - secure_allow_features = 0; -#else constant char *str = lgetenv("LESSSECURE"); if (isnullenv(str)) secure_allow_features = ~0; /* allow everything */ @@ -232,7 +189,8 @@ static void init_secure(void) str = lgetenv("LESSSECURE_ALLOW"); if (!isnullenv(str)) - parse_csl(set_security_feature, str, NULL); + secure_allow_features = parse_csl_bitmap(str, + security_features, countof(security_features), "LESSSECURE_ALLOW"); #endif } @@ -294,7 +252,7 @@ int main(int argc, constant char *argv[]) * Process command line arguments and LESS environment arguments. * Command line arguments override environment arguments. */ - is_tty = isatty(1); + is_tty = (isatty(1) != 0); init_mark(); init_cmds(); init_poll(); @@ -347,7 +305,8 @@ int main(int argc, constant char *argv[]) quit(QUIT_OK); } - get_term(); + if (is_tty) + get_term(); expand_cmd_tables(); #if EDITOR @@ -413,10 +372,10 @@ int main(int argc, constant char *argv[]) * Output is not a tty. * Just copy the input file(s) to output. */ - set_output(1, TRUE); /* write to stdout */ SET_BINARY(1); if (edit_first() == 0) { + set_output(1, TRUE); /* write to stdout */ do { cat_file(); } while (edit_next(1) == 0); @@ -161,6 +161,7 @@ static struct mark * getmark(char c) { struct mark *m; static struct mark sm; + POSITION pos; switch (c) { @@ -181,7 +182,13 @@ static struct mark * getmark(char c) return (NULL); } m = &sm; - cmark(m, curr_ifile, ch_tell(), sc_height); + pos = ch_tell(); + if (pos == NULL_POSITION) + return (NULL); + pos = back_line(pos, NULL); + if (pos == NULL_POSITION) + return (NULL); + cmark(m, curr_ifile, pos, sc_height-1); break; case '.': /* @@ -225,19 +232,35 @@ public lbool badmark(char c) /* * Set a user-defined mark. */ -public void setmark(char c, int where) +public void setmark(char c, int where, LINENUM linenum) { struct mark *m; struct scrpos scrpos; + POSITION pos; m = getumark(c); if (m == NULL) return; - get_scrpos(&scrpos, where); - if (scrpos.pos == NULL_POSITION) + + if (linenum == 0) { - lbell(); - return; + get_scrpos(&scrpos, where); + if (scrpos.pos == NULL_POSITION) + { + lbell(); + return; + } + } else + { + pos = find_pos(linenum); + if (pos == NULL_POSITION) + { + PARG parg; + parg.p_linenum = linenum; + error("Cannot find line number %n", &parg); + return; + } + get_scrpos_pos(&scrpos, where, pos); } cmark(m, curr_ifile, scrpos.pos, scrpos.ln); marks_modified = TRUE; @@ -260,7 +283,12 @@ public void clrmark(char c) lbell(); return; } - m->m_scrpos.pos = NULL_POSITION; + mark_clear(m); +#if CMD_HISTORY + /* Also clear in file_marks, so save_marks doesn't save it to history file. */ + m = &file_marks[mark_index(c)]; + mark_clear(m); +#endif marks_modified = TRUE; if (perma_marks && autosave_action('m')) save_cmdhist(); @@ -285,7 +313,7 @@ public void lastmark(void) /* * Go to a mark. */ -public void gomark(char c) +public void gomark(char c, int sline) { struct mark *m; struct scrpos scrpos; @@ -293,6 +321,8 @@ public void gomark(char c) m = getmark(c); if (m == NULL) return; + if (sline != 0) + m->m_scrpos.ln = sline; /* * If we're trying to go to the lastmark and @@ -466,10 +496,6 @@ public void restore_mark(constant char *line) ln = lstrtoic(line, &line, 10); if (ln < 0) return; - if (ln < 1) - ln = 1; - if (ln > sc_height) - ln = sc_height; skip_whitespace; pos = lstrtoposc(line, &line, 10); if (pos < 0) diff --git a/optfunc.c b/optfunc.c index 2370103349a0..a39e93181be7 100644 --- a/optfunc.c +++ b/optfunc.c @@ -34,10 +34,11 @@ extern lbool plusoption; extern int swindow; extern int sc_width; extern int sc_height; -extern int dohelp; +extern lbool dohelp; extern char openquote; extern char closequote; extern char *prproto[]; +extern char *eprproto[]; extern char *eqproto; extern char *hproto; extern char *wproto; @@ -53,7 +54,9 @@ extern int match_shift; extern long match_shift_fraction; extern LWCHAR rscroll_char; extern int rscroll_attr; -extern int mousecap; +extern int emouse; +extern int mouse_reverse; +extern int xmouse; extern int wheel_lines; extern int less_is_more; extern int linenum_width; @@ -68,6 +71,7 @@ extern int tabstops[]; extern int ntabstops; extern int tabdefault; extern int no_paste; +extern int hilite_target; extern char intr_char; extern int nosearch_header_lines; extern int nosearch_header_cols; @@ -87,7 +91,7 @@ extern char ztags[]; #endif #if LESSTEST extern constant char *ttyin_name; -extern int is_tty; +extern lbool is_tty; #endif /*LESSTEST*/ #if MSDOS_COMPILER extern int nm_fg_color, nm_bg_color, nm_attr; @@ -333,7 +337,7 @@ public void opt__S(int type, constant char *s) switch (type) { case TOGGLE: - pos_rehead(); + pos_rehead(TRUE); break; } } @@ -469,7 +473,49 @@ public void opt__P(int type, constant char *s) break; case QUERY: parg.p_string = prproto[pr_type]; - error("%s", &parg); + switch (pr_type) + { + case PR_MEDIUM: error("Prompt (medium): %s", &parg); break; + case PR_LONG: error("Prompt (long): %s", &parg); break; + default: error("Prompt (short): %s", &parg); break; + } + break; + } +} + +/* + * Handler for --end-prompt option. + */ +public void opt_end_prompt(int type, constant char *s) +{ + char **pend; + PARG parg; + + switch (type) + { + case INIT: + case TOGGLE: + switch (*s) + { + case 's': pend = &eprproto[PR_SHORT]; s++; break; + case 'm': pend = &eprproto[PR_MEDIUM]; s++; break; + case 'M': pend = &eprproto[PR_LONG]; s++; break; + default: pend = &eprproto[PR_SHORT]; break; + } + if (*pend != NULL) + free(*pend); + *pend = (strcmp(s, "-") == 0) ? NULL : save(s); + break; + case QUERY: + parg.p_string = eprproto[pr_type]; + if (parg.p_string == NULL) + parg.p_string = "(nothing)"; + switch (pr_type) + { + case PR_MEDIUM: error("Print after medium prompt: %s", &parg); break; + case PR_LONG: error("Print after long prompt: %s", &parg); break; + default: error("Print after short prompt: %s", &parg); break; + } break; } } @@ -613,11 +659,13 @@ static int color_from_namechar(char namechar) case 'C': return AT_COLOR_CTRL; case 'E': return AT_COLOR_ERROR; case 'H': return AT_COLOR_HEADER; + case 'J': return AT_COLOR_TARGET; case 'M': return AT_COLOR_MARK; case 'N': return AT_COLOR_LINENUM; case 'P': return AT_COLOR_PROMPT; case 'R': return AT_COLOR_RSCROLL; case 'S': return AT_COLOR_SEARCH; + case 'T': return AT_COLOR_TILDE; case 'W': case 'A': return AT_COLOR_ATTN; case 'n': return AT_NORMAL; case 's': return AT_STANDOUT; @@ -648,6 +696,11 @@ public void opt_D(int type, constant char *s) if (*s == 'a') { sgr_mode = !sgr_mode; + if (type == TOGGLE) + { + p.p_string = (sgr_mode) ? "on" : "off"; + error("SGR mode is %s", &p); + } break; } #endif @@ -700,12 +753,6 @@ public void opt_D(int type, constant char *s) return; } break; -#if MSDOS_COMPILER - case QUERY: - p.p_string = (sgr_mode) ? "on" : "off"; - error("SGR mode is %s", &p); - break; -#endif } } @@ -868,7 +915,7 @@ public void opt_query(int type, constant char *s) error("Use \"h\" for help", NULL_PARG); break; case INIT: - dohelp = 1; + dohelp = TRUE; } } @@ -897,20 +944,99 @@ public void calc_match_shift(void) } /* + * Handler for the --emouse option. + */ + /*ARGSUSED*/ +public void opt_emouse(int type, constant char *s) +{ + /* Order of entries matters for QUERY. + * Combinations must come after their components. */ + static struct csl_bitmap_def emouse_defs[] = { + { "hscroll", EMOUSE_HSCROLL }, + { "vscroll", EMOUSE_VSCROLL }, + { "hdrag", EMOUSE_HDRAG }, + { "vdrag", EMOUSE_VDRAG }, + { "lclick", EMOUSE_LCLICK }, + { "rclick", EMOUSE_RCLICK }, + { "scroll", EMOUSE_HSCROLL|EMOUSE_VSCROLL }, + { "drag", EMOUSE_HDRAG|EMOUSE_VDRAG }, + { "hmove", EMOUSE_HSCROLL|EMOUSE_HDRAG }, + { "vmove", EMOUSE_VSCROLL|EMOUSE_VDRAG }, + { "move", EMOUSE_VSCROLL|EMOUSE_VDRAG|EMOUSE_HSCROLL|EMOUSE_HDRAG }, + { "click", EMOUSE_LCLICK|EMOUSE_RCLICK }, + { "all", EMOUSE_VSCROLL|EMOUSE_VDRAG|EMOUSE_HSCROLL|EMOUSE_HDRAG|EMOUSE_LCLICK|EMOUSE_RCLICK }, + }; + + switch (type) + { + case INIT: + case TOGGLE: { + lbool was_mouse_enabled = (emouse != 0); + if (s == NULL || strcmp(s, "-") == 0) + emouse = 0; + else + emouse = parse_csl_bitmap(s, + emouse_defs, countof(emouse_defs), "--emouse"); + if (type == TOGGLE && was_mouse_enabled != (emouse != 0)) + { + if (emouse == 0) + deinit_mouse(); + else + init_mouse(); + } + break; } + case QUERY: { + char buf[128]; + char *bp = buf; + char *ebuf = buf + sizeof(buf); + int qmouse = emouse; + PARG parg; + int i; + + for (i = countof(emouse_defs)-1; i >= 0; i--) + { + int bit = emouse_defs[i].bit_value; + if ((qmouse & bit) == bit) + { + if (bp > buf && bp+1 < ebuf) + *bp++ = ','; + strncpy(bp, emouse_defs[i].bit_name, ptr_diff(ebuf, bp)); + bp += strlen(bp); + qmouse &= ~bit; + } + } + *bp = '\0'; + parg.p_string = buf; + if (buf[0] == '\0') + error("Ignore mouse input", NULL_PARG); + else + error("Mouse features enabled: %s", &parg); + break; } + } +} + +/* * Handler for the --mouse option. */ /*ARGSUSED*/ -public void opt_mousecap(int type, constant char *s) +public void opt_mouse(int type, constant char *s) { switch (type) { + case INIT: case TOGGLE: - if (mousecap == OPT_OFF) - deinit_mouse(); - else - init_mouse(); + switch (xmouse) + { + case OPT_OFF: + opt_emouse(type, "-"); + break; + case OPT_ON: + case OPT_ONPLUS: + opt_emouse(type, "vmove,click"); + mouse_reverse = (xmouse == OPT_ONPLUS); + break; + } break; - case INIT: case QUERY: break; } @@ -1116,13 +1242,31 @@ public void opt_header(int type, constant char *s) set_header(start_pos); calc_jump_sline(); break; } - case QUERY: { - char buf[3*INT_STRLEN_BOUND(long)+3]; - PARG parg; - SNPRINTF3(buf, sizeof(buf), "%ld,%ld,%ld", (long) header_lines, (long) header_cols, (long) find_linenum(header_start_pos)); - parg.p_string = buf; - error("Header (lines,columns,line-number) is %s", &parg); - break; } + case QUERY: { + char buf[3*INT_STRLEN_BOUND(long)+3]; + PARG parg; + SNPRINTF3(buf, sizeof(buf), "%ld,%ld,%ld", (long) header_lines, (long) header_cols, (long) find_linenum(header_start_pos)); + parg.p_string = buf; + error("Header (lines,columns,line-number) is %s", &parg); + break; } + } +} + +/* + * Handler for the --hilite-target option. + */ + /*ARGSUSED*/ +public void opt_hilite_target(int type, constant char *s) +{ + switch (type) + { + case INIT: + break; + case TOGGLE: + draw_target_attn(hilite_target != OPT_OFF); + break; + case QUERY: + break; } } @@ -1242,11 +1386,11 @@ public void opt_no_paste(int type, constant char *s) init_bracketed_paste(); else deinit_bracketed_paste(); - break; + break; case INIT: case QUERY: break; - } + } } #if LESSTEST @@ -1260,7 +1404,7 @@ public void opt_ttyin_name(int type, constant char *s) { case INIT: ttyin_name = s; - is_tty = 1; + is_tty = TRUE; break; } } @@ -50,6 +50,7 @@ public int no_init; /* Disable sending ti/te termcap strings */ public int no_keypad; /* Disable sending ks/ke termcap strings */ public int twiddle; /* Show tildes after EOF */ public int show_attn; /* Hilite first unread line */ +public int hilite_target; /* Hilite target line */ public int status_col; /* Display a status column */ public int use_lessopen; /* Use the LESSOPEN filter */ public int quit_on_intr; /* Quit on interrupt */ @@ -59,7 +60,9 @@ public int opt_use_backslash; /* Use backslash escaping in option parsing */ public LWCHAR rscroll_char; /* Char which marks chopped lines with -S */ public int rscroll_attr; /* Attribute of rscroll_char */ public int no_hist_dups; /* Remove dups from history list */ -public int mousecap; /* Allow mouse for scrolling */ +public int emouse; /* Enabled mouse features */ +public int mouse_reverse; /* Reverse mouse wheel scrolling direction */ +public int xmouse; /* Old --mouse option, replaced by --emouse */ public int wheel_lines; /* Number of lines to scroll on mouse wheel scroll */ public int perma_marks; /* Save marks in history file */ public int linenum_width; /* Width of line numbers */ @@ -85,10 +88,12 @@ public int match_shift; /* Extra horizontal shift on search match */ public int no_paste; /* Don't accept pasted input */ public int no_edit_warn; /* Don't warn when editing a LESSOPENed file */ public int stop_on_form_feed; /* Stop scrolling on a line starting with form feed */ +public int past_eof; /* Continue scrolling past EOF */ public long match_shift_fraction = NUM_FRAC_DENOM/2; /* 1/2 of screen width */ public char intr_char = CONTROL('X'); /* Char to interrupt reads */ public char *first_cmd_at_prompt = NULL; /* Command to exec before first prompt */ public char *autosave; /* Actions which do autosave of history file */ +public char *end_prompt; /* Printed after clearing the prompt */ #if HILITE_SEARCH public int hilite_search; /* Highlight matched search patterns? */ #endif @@ -157,7 +162,9 @@ static struct optname follow_optname = { "follow-name", NULL }; static struct optname use_backslash_optname = { "use-backslash", NULL }; static struct optname rscroll_optname = { "rscroll", NULL }; static struct optname nohistdups_optname = { "no-histdups", NULL }; -static struct optname mousecap_optname = { "mouse", NULL }; +static struct optname mouse_optname = { "mouse", NULL }; +static struct optname emouse_optname = { "emouse", NULL }; +static struct optname mouse_reverse_optname = { "rmouse", NULL }; static struct optname wheel_lines_optname = { "wheel-lines", NULL }; static struct optname perma_marks_optname = { "save-marks", NULL }; static struct optname linenum_width_optname = { "line-num-width", NULL }; @@ -169,6 +176,7 @@ static struct optname status_line_optname = { "status-line", NULL }; static struct optname header_optname = { "header", NULL }; static struct optname no_paste_optname = { "no-paste", NULL }; static struct optname form_feed_optname = { "form-feed", NULL }; +static struct optname past_eof_optname = { "past-eof", NULL }; static struct optname no_edit_warn_optname2 = { "no-warn-edit", NULL }; static struct optname no_edit_warn_optname = { "no-edit-warn", &no_edit_warn_optname2 }; static struct optname nonum_headers_optname = { "no-number-headers", NULL }; @@ -189,6 +197,8 @@ static struct optname proc_return_optname = { "proc-return", NULL }; static struct optname match_shift_optname = { "match-shift", NULL }; static struct optname first_cmd_at_prompt_optname = { "cmd", NULL }; static struct optname autosave_optname = { "autosave", NULL }; +static struct optname hilite_target_optname = { "hilite-target", NULL }; +static struct optname end_prompt_optname = { "end-prompt", NULL }; #if LESSTEST static struct optname ttyin_name_optname = { "tty", NULL }; #endif /*LESSTEST*/ @@ -439,6 +449,14 @@ static struct loption option[] = O_NOVAR, 0, NULL, opt__V, { NULL, NULL, NULL } }, + { OLETTER_NONE, &hilite_target_optname, + O_BOOL, OPT_OFF, &hilite_target, opt_hilite_target, + { + "Don't highlight target line", + "Highlight target line", + NULL + } + }, { 'w', &w_optname, O_TRIPLE|O_REPAINT, OPT_OFF, &show_attn, NULL, { @@ -530,8 +548,8 @@ static struct loption option[] = { OLETTER_NONE, &use_backslash_optname, O_BOOL, OPT_OFF, &opt_use_backslash, NULL, { - "Use backslash escaping in command line parameters", "Don't use backslash escaping in command line parameters", + "Use backslash escaping in command line parameters", NULL } }, @@ -547,12 +565,24 @@ static struct loption option[] = NULL } }, - { OLETTER_NONE, &mousecap_optname, - O_TRIPLE, OPT_OFF, &mousecap, opt_mousecap, + { OLETTER_NONE, &mouse_optname, + O_TRIPLE, OPT_OFF, &xmouse, opt_mouse, { "Ignore mouse input", - "Use the mouse for scrolling", - "Use the mouse for scrolling (reverse)" + "Use the mouse for scrolling vertically", + "Use the mouse for scrolling vertically (reverse)" + } + }, + { OLETTER_NONE, &emouse_optname, + O_STRING, 0, NULL, opt_emouse, + { "Mouse features: ", "s", NULL } + }, + { OLETTER_NONE, &mouse_reverse_optname, + O_BOOL, OPT_OFF, &mouse_reverse, NULL, + { + "Normal mouse scroll direction", + "Reverse mouse scroll direction", + NULL } }, { OLETTER_NONE, &wheel_lines_optname, @@ -614,8 +644,8 @@ static struct loption option[] = { OLETTER_NONE, &status_line_optname, O_BOOL|O_REPAINT, OPT_OFF, &status_line, NULL, { - "Don't color each line with its status column color", - "Color each line with its status column color", + "Line highlight applies to text only", + "Line highlight applies to entire width of screen", NULL } }, @@ -639,6 +669,14 @@ static struct loption option[] = NULL } }, + { OLETTER_NONE, &past_eof_optname, + O_BOOL, OPT_OFF, &past_eof, NULL, + { + "Stop scrolling at end of file", + "Don't stop scrolling at end of file", + NULL + } + }, { OLETTER_NONE, &no_edit_warn_optname, O_BOOL, OPT_OFF, &no_edit_warn, NULL, { @@ -769,6 +807,10 @@ static struct loption option[] = O_STRING|O_INIT_HANDLER, 0, NULL, opt_autosave, { "Autosave actions: ", "s", NULL } }, + { OLETTER_NONE, &end_prompt_optname, + O_STRING, 0, NULL, opt_end_prompt, + { "Print after prompt: ", "s", NULL } + }, #if LESSTEST { OLETTER_NONE, &ttyin_name_optname, O_STRING|O_NO_TOGGLE, 0, NULL, opt_ttyin_name, @@ -80,7 +80,6 @@ static lbool any_data = FALSE; static lbool reading; static lbool opening; public lbool waiting_for_data; -public int consecutive_nulls = 0; public lbool getting_one_screen = FALSE; /* Milliseconds to wait for data before displaying "waiting for data" message. */ @@ -97,9 +96,9 @@ extern int exit_F_on_close; extern int follow_mode; extern int scanning_eof; extern char intr_char; -extern int is_tty; +extern lbool is_tty; extern int quit_if_one_screen; -extern int one_screen; +extern lbool one_screen; #if HAVE_TIME extern time_type less_start_time; #endif @@ -305,46 +304,36 @@ start: if (ret != 0) { if (ret == READ_INTR) + { sigs |= S_SWINTERRUPT; + getcc_clear(); + } reading = FALSE; return (ret); } } #else #if MSDOS_COMPILER==WIN32C - if (!(quit_if_one_screen && one_screen) && win32_kbhit2(TRUE)) + if (!(quit_if_one_screen && one_screen)) { - int c = WIN32getch(); - if (c == CONTROL('C') || c == intr_char) + char c; + if (win32_kbhit2(&c)) { - sigs |= S_SWINTERRUPT; - reading = FALSE; - return (READ_INTR); + if (c == CONTROL('C') || c == intr_char) + { + sigs |= S_SWINTERRUPT; + reading = FALSE; + win32_clear_queue(); + return (READ_INTR); + } + win32_enqueue((int) c); } - WIN32ungetch(c); } #endif #endif n = read(fd, buf, len); reading = FALSE; -#if 0 - /* - * This is a kludge to workaround a problem on some systems - * where terminating a remote tty connection causes read() to - * start returning 0 forever, instead of -1. - */ - { - if (!ignore_eoi) - { - if (n == 0) - consecutive_nulls++; - else - consecutive_nulls = 0; - if (consecutive_nulls > 20) - quit(QUIT_ERROR); - } - } -#endif + if (n < 0) { #if HAVE_ERRNO @@ -21,17 +21,22 @@ #endif public int errmsgs; /* Count of messages displayed by error() */ -public int need_clr; -public int final_attr; +public lbool prompting = FALSE; +static lbool need_clr = FALSE; extern int sigs; extern int sc_width; extern int so_s_width, so_e_width; -extern int is_tty; +extern lbool is_tty; extern int oldbot; extern int utf_mode; +extern int status_col; +extern int status_line; +extern int hilite_target; +extern int use_color; extern char intr_char; extern lbool term_init_ever; +extern int pr_type; #if MSDOS_COMPILER==WIN32C || MSDOS_COMPILER==BORLANDC || MSDOS_COMPILER==DJGPPC extern int ctldisp; @@ -49,11 +54,13 @@ extern int vt_enabled; /* * Display the line which is in the line buffer. */ -public void put_line(lbool forw_scroll) +public void put_line_hilite(lbool forw_scroll, lbool target) { int c; size_t i; int a; + lbool empty_line = TRUE; + constant int target_attr = use_color ? AT_COLOR_TARGET : AT_UNDERLINE; if (ABORT_SIGS()) { @@ -64,12 +71,27 @@ public void put_line(lbool forw_scroll) return; } - final_attr = AT_NORMAL; - for (i = 0; (c = gline(i, &a)) != '\0'; i++) { + if (target && a == AT_NORMAL) + { + /* We're highlighting this line as the target line. Highlight + * this char if it's not already highlighted, and either we're + * highlighting the whole line or we're highlighting only the + * status column and this is the status column. */ + if ((status_col && i == 0) || + (i >= line_pfx_width() && (status_line || !status_col))) + a = target_attr; + } + if (target && (c == '\n' || c == '\r') && empty_line) + { + /* Line is empty; add a space to carry the target hilite. */ + at_switch(target_attr); + putchr(' '); + } + if (!(a & AT_ANSI)) + empty_line = FALSE; at_switch(a); - final_attr = a; if (c == '\b') putbs(); else @@ -81,6 +103,11 @@ public void put_line(lbool forw_scroll) clear_eol(); } +public void put_line(lbool forw_scroll) +{ + put_line_hilite(forw_scroll, FALSE); +} + /* * win_flush has at least one non-critical issue when an escape sequence * begins at the last char of the buffer, and possibly more issues. @@ -466,25 +493,14 @@ public int putchr(int ch) */ if (!term_init_ever && outfd == 1) term_init(); - -#if 0 /* fake UTF-8 output for testing */ - if (utf_mode) + if (prompting) { - static char ubuf[MAX_UTF_CHAR_LEN]; - static int ubuf_len = 0; - static int ubuf_index = 0; - if (ubuf_len == 0) - { - ubuf_len = utf_len(c); - ubuf_index = 0; - } - ubuf[ubuf_index++] = c; - if (ubuf_index < ubuf_len) - return c; - c = get_wchar(ubuf) & 0xFF; - ubuf_len = 0; + constant char *epr = end_pr_string(); + prompting = FALSE; + if (epr != NULL) + putstr(epr); } -#endif + clear_bot_if_needed(); #if MSDOS_COMPILER if (c == '\n' && is_tty) @@ -512,7 +528,7 @@ public void clear_bot_if_needed(void) { if (!need_clr) return; - need_clr = 0; + need_clr = FALSE; clear_bot(); } @@ -743,7 +759,7 @@ static void ierror_suffix(constant char *fmt, constant PARG *parg, constant char putstr(suffix3); at_exit(); flush(); - need_clr = 1; + need_clr = TRUE; } public void ierror(constant char *fmt, constant PARG *parg) diff --git a/pattern.c b/pattern.c index 228c89b49fcc..47b449e1c7ca 100644 --- a/pattern.c +++ b/pattern.c @@ -147,7 +147,11 @@ public int compile_pattern(constant char *pattern, int search_type, int show_err { int result; - if (caseless != OPT_ONPLUS || (re_handles_caseless && !(search_type & SRCH_NO_REGEX))) +#if RE_HANDLES_CASELESS + if (caseless != OPT_ONPLUS || (!(search_type & SRCH_NO_REGEX))) +#else + if (caseless != OPT_ONPLUS) +#endif { result = compile_pattern2(pattern, search_type, comp_pattern, show_error); } else @@ -391,7 +395,7 @@ static lbool match_pattern1(PATTERN_TYPE pattern, constant char *tpattern, const #if HAVE_PCRE2 { int flags = (notbol) ? PCRE2_NOTBOL : 0; - pcre2_match_data *md = pcre2_match_data_create(nsp-1, NULL); + pcre2_match_data *md = pcre2_match_data_create_from_pattern(pattern, NULL); int mcount = pcre2_match(pattern, (PCRE2_SPTR)line, line_len, line_off, flags, md, NULL); matched = (mcount > 0); diff --git a/pattern.h b/pattern.h index 335a316da8e4..23349ecea0b1 100644 --- a/pattern.h +++ b/pattern.h @@ -24,7 +24,7 @@ #endif #define PATTERN_TYPE regex_t * #define SET_NULL_PATTERN(name) name = NULL -#define re_handles_caseless TRUE +#define RE_HANDLES_CASELESS 1 #endif /* ---- PCRE ---- */ @@ -32,7 +32,7 @@ #include <pcre.h> #define PATTERN_TYPE pcre * #define SET_NULL_PATTERN(name) name = NULL -#define re_handles_caseless TRUE +#define RE_HANDLES_CASELESS 1 #endif /* ---- PCRE2 ---- */ @@ -41,7 +41,7 @@ #include <pcre2.h> #define PATTERN_TYPE pcre2_code * #define SET_NULL_PATTERN(name) name = NULL -#define re_handles_caseless TRUE +#define RE_HANDLES_CASELESS 1 #endif /* ---- RE_COMP ---- */ @@ -75,6 +75,6 @@ extern int reg_show_error; #define SET_NULL_PATTERN(name) #endif -#ifndef re_handles_caseless -#define re_handles_caseless FALSE +#ifndef RE_HANDLES_CASELESS +#define RE_HANDLES_CASELESS 0 #endif diff --git a/position.c b/position.c index 442e6c929f6f..2f67925a62cb 100644 --- a/position.c +++ b/position.c @@ -157,7 +157,7 @@ public lbool empty_lines(int s, int e) int i; for (i = s; i <= e; i++) - if (table[i] != NULL_POSITION && table[i] != 0) + if (table[i] != NULL_POSITION) return FALSE; return TRUE; } @@ -170,7 +170,7 @@ public lbool empty_lines(int s, int e) * such that the top few lines are empty, we may have to set * the screen line to a number > 0. */ -public void get_scrpos(struct scrpos *scrpos, int where) +public void get_scrpos_pos(struct scrpos *scrpos, int where, POSITION pos) { int i; int dir; @@ -194,24 +194,52 @@ public void get_scrpos(struct scrpos *scrpos, int where) break; } - /* - * Find the first line on the screen which has something on it, - * and return the screen line number and the file position. - */ - for (;; i += dir) + if (pos != NULL_POSITION) { - if (table[i] != NULL_POSITION) + scrpos->ln = i+1; + scrpos->pos = pos; + } else + { + /* + * Find the first line on the screen which has something on it, + * and return the screen line number and the file position. + */ + for (;; i += dir) { - scrpos->ln = i+1; - scrpos->pos = table[i]; - return; + if (table[i] != NULL_POSITION) + { + scrpos->ln = i+1; + scrpos->pos = table[i]; + return; + } + if (i == last) break; } - if (i == last) break; + /* The screen is empty. */ + scrpos->pos = NULL_POSITION; } +} + +public void get_scrpos(struct scrpos *scrpos, int where) +{ + get_scrpos_pos(scrpos, where, NULL_POSITION); +} + +/* + * Convert sline to sindex and clip to screen size. + */ +static int sindex_from_sline_clipped(int sline) +{ /* - * The screen is empty. + * Can't be less than 1 or greater than sc_height-1. */ - scrpos->pos = NULL_POSITION; + if (sline <= 0) + sline = 1; + if (sline >= sc_height) + sline = sc_height-1; + /* + * Return zero-based line number, not one-based. + */ + return (sline-1); } /* @@ -231,17 +259,7 @@ public int sindex_from_sline(int sline) */ if (sline < 0) sline += sc_height; - /* - * Can't be less than 1 or greater than sc_height-1. - */ - if (sline <= 0) - sline = 1; - if (sline >= sc_height) - sline = sc_height-1; - /* - * Return zero-based line number, not one-based. - */ - return (sline-1); + return sindex_from_sline_clipped(sline); } /* @@ -273,12 +291,14 @@ static int pos_shift(POSITION linepos, size_t choff) * Return the position of the first char of the line containing tpos. * Thus if tpos is the first char of its line, just return tpos. */ -static POSITION beginning_of_line(POSITION tpos) +public POSITION beginning_of_line(POSITION tpos) { ch_seek(tpos); while (ch_tell() != ch_zero()) { int ch = ch_back_get(); + if (ch == EOI) + break; /* {{ probably unnecessary due to ch_zero() check }} */ if (ch == '\n') { (void) ch_forw_get(); @@ -291,10 +311,11 @@ static POSITION beginning_of_line(POSITION tpos) /* * When viewing long lines, it may be that the first char in the top screen * line is not the first char in its (file) line (the table is "beheaded"). - * This function sets that entry to the position of the first char in the line, - * and sets hshift so that the first char in the first line is unchanged. + * This function sets that entry to the position of the first char in the + * line, and optionally sets hshift so that the first char in the first line + * is unchanged. */ -public void pos_rehead(void) +public void pos_rehead(lbool adj_hshift) { POSITION linepos; POSITION tpos = table[TOP]; @@ -304,6 +325,7 @@ public void pos_rehead(void) if (linepos == tpos) return; table[TOP] = linepos; - hshift = pos_shift(linepos, (size_t) (tpos - linepos)); + if (adj_hshift) + hshift = pos_shift(linepos, (size_t) (tpos - linepos)); screen_trashed(); } @@ -32,7 +32,7 @@ extern int header_lines; extern int utf_mode; extern IFILE curr_ifile; #if OSC8_LINK -extern char *osc8_path; +extern POSITION osc8_linepos; #endif #if EDITOR extern constant char *editor; @@ -59,6 +59,7 @@ static constant char more_proto[] = "--More--(?eEND ?x- Next\\: %x.:?pB%pB\\%:byte %bB?s/%s...%t)"; public char *prproto[3]; +public char *eprproto[3]; public char constant *eqproto = e_proto; public char constant *hproto = h_proto; public char constant *wproto = w_proto; @@ -75,6 +76,7 @@ public void init_prompt(void) prproto[0] = save(s_proto); prproto[1] = save(less_is_more ? more_proto : m_proto); prproto[2] = save(M_proto); + eprproto[0] = eprproto[1] = eprproto[2] = NULL; eqproto = save(e_proto); hproto = save(h_proto); wproto = save(w_proto); @@ -241,6 +243,12 @@ static lbool cond(char c, int where) #else return (new_file ? TRUE : FALSE); #endif + case 'O': /* OSC 8 link selected? */ +#if OSC8_LINK + return (osc8_linepos != NULL_POSITION); +#else + return FALSE; +#endif case 'p': /* Percent into file (bytes) known? */ return (curr_byte(where) != NULL_POSITION && ch_length() > 0); case 'P': /* Percent into file (lines) known? */ @@ -368,14 +376,6 @@ static void protochar(char c, int where) #endif ap_int(nifile()); break; } - case 'o': /* path (URI without protocol) of selected OSC8 link */ -#if OSC8_LINK - if (osc8_path != NULL) - ap_str(osc8_path); - else -#endif - ap_quest(); - break; case 'p': /* Percent into file (bytes) */ pos = curr_byte(where); len = ch_length(); @@ -599,6 +599,21 @@ public constant char * pr_string(void) } /* + * Return the end prompt string. + */ +public constant char * end_pr_string(void) +{ + int type; + + if (ch_getflags() & CH_HELPFILE) + return NULL; + type = (!less_is_more) ? pr_type : pr_type ? 0 : 1; + if (eprproto[type] == NULL) + return NULL; + return pr_expand(eprproto[type]); +} + +/* * Return a message suitable for printing while waiting in the F command. */ public constant char * wait_message(void) @@ -25,6 +25,8 @@ * *** NOTE: this code has been altered slightly for use in Tcl. *** * Slightly modified by David MacKenzie to undo most of the changes for TCL. * Added regexec2 with notbol parameter. -- 4/19/99 Mark Nudelman + * Change functions style from K&R to C89 -- 2023-09 Avi Halachmi + * Add support for character classes [:NAME:] -- 2026-02 Avi Halachmi */ #include "less.h" @@ -47,16 +49,13 @@ * regstart char that must begin a match; '\0' if none obvious * reganch is the match anchored (at beginning-of-line only)? * regmust string (pointer into program) that match must include, or NULL - * regmlen length of regmust string * * Regstart and reganch permit very fast decisions on suitable starting points * for a match, cutting down the work a lot. Regmust permits fast rejection * of lines that cannot possibly match. The regmust tests are costly enough * that regcomp() supplies a regmust only if the r.e. contains something * potentially expensive (at present, the only such thing detected is * or + - * at the start of the r.e., which can involve a lot of backup). Regmlen is - * supplied because the test in regexec() needs it and regcomp() is - * computing it anyway. + * at the start of the r.e., which can involve a lot of backup). */ /* @@ -251,7 +250,6 @@ regcomp(constant char *exp) r->regstart = '\0'; /* Worst-case defaults. */ r->reganch = 0; r->regmust = NULL; - r->regmlen = 0; scan = r->program+1; /* First BRANCH. */ if (OP(regnext(scan)) == END) { /* Only one top-level choice. */ scan = OPERAND(scan); @@ -276,10 +274,10 @@ regcomp(constant char *exp) for (; scan != NULL; scan = regnext(scan)) if (OP(scan) == EXACTLY && ((int) strlen(OPERAND(scan))) >= len) { longest = OPERAND(scan); + /* redundant strlen, not critical in regcomp */ len = (int) strlen(OPERAND(scan)); } r->regmust = longest; - r->regmlen = len; } } @@ -459,6 +457,126 @@ regpiece(int *flagp) } /* + * Handling of character classes [:NAME:] + * + * - We only cover C/POSIX locale (ASCII). + * - We identify the 12 POSIX classes. + * - We error on unknown [:THING:]. + * - [=EQUIV=] or [.COLLATE.] are NOT detected, and considered non-special. + * - [:NAME:] errors on either side of '-' range (but not if the '-' is + * literal - at the beginning or end of the [...]). + * - The logic is confined to regbracket(), and only used during regcomp. + * + * POSIX regex, classes, collation, etc: + * https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap09.html + * https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/V1_chap07.html + */ + +typedef struct cclass { + constant size_t len; /* of id */ + constant char *id; + constant char *chars; +} cclass; + +static constant cclass cclasses[] = { + /* first two chars of id are ignored, and expected to be "[:" */ + {9, "[:alnum:]", "0-9A-Za-z"}, + {9, "[:alpha:]", "A-Za-z"}, + {9, "[:blank:]", "\t "}, + {9, "[:cntrl:]", "\x01-\x1f\x7f"}, + {9, "[:digit:]", "0-9"}, + {9, "[:graph:]", "\x21-\x7e"}, + {9, "[:lower:]", "a-z"}, + {9, "[:print:]", "\x20-\x7e"}, + {9, "[:punct:]", "!-/:-@[-`{|}~"}, + {9, "[:space:]", "\t\n\v\f\r "}, + {9, "[:upper:]", "A-Z"}, + {10, "[:xdigit:]", "0-9A-Fa-f"}, +}; + +/* returns index>=0 in cclasses if s starts with known [:NAME:], + * else -2 on error (s starts with unknown [:THING:]), + * else -1 (not-special). + * + * we could create a wrapper macro which tests '[' and ':' before + * calling cclass_idx(s) - to avoid a function call on early abort, + * and/or replace the string search in cclass_idx with binary search + * or something else, but this is not hot code, so keep it simple. + */ +static int +cclass_idx(constant char *s) +{ + int i; + constant char *p; + + if (*s++ != '[' || *s++ != ':') + return -1; + + /* s is past the "[:" prefix */ + for (i = 0; i < countof(cclasses); ++i) + if (strncmp(s, cclasses[i].id + 2, cclasses[i].len - 2) == 0) + return i; /* found */ + + p = strchr(s, ']'); + if (p && p != s && p[-1] == ':') + return -2; /* unrecognized [:THING:] */ + + return -1; /* not special as far as we can tell */ +} + +/* Calls regc(c) for each char which a bracket expression matches, + * without touching the global regparse. + * + * The caller should ensure that ANYOF or ANYBUT node was already added + * (depending on whether it starts with "[" or "[^"), and "in" should + * point to the first data char after this prefix. + * + * calls FAIL(...) and returns NULL on failure, + * or returns a pointer to the first unprocessed char (']' or '\0'). + * the caller may then update the global regparse, and add final regc(0). + */ +static constant char * +regbracket(constant char *in) +{ + register int clss; + register int classend; + int idx; + + if (*in == ']' || *in == '-') + regc(*in++); + while (*in != '\0' && *in != ']') { + if (*in == '-') { + in++; + if (cclass_idx(in) != -1) + FAIL("invalid [] range end"); /* X-[:NAME:] */ + if (*in == ']' || *in == '\0') + regc('-'); + else { + clss = UCHARAT(in-2)+1; + classend = UCHARAT(in); + if (clss > classend+1) + FAIL("invalid [] range"); + for (; clss <= classend; clss++) + regc(clss); + in++; + } + } else if ((idx = cclass_idx(in)) == -1) { + regc(*in++); + } else if (idx == -2) { + FAIL("unknown [:CLASS:] name"); + } else { /* idx is a valid index, add class chars */ + if (regbracket(cclasses[idx].chars) == NULL) + return(NULL); /* should be unreachable */ + in += cclasses[idx].len; + + if (*in == '-' && in[1] != '\0' && in[1] != ']') + FAIL("invalid [] range start"); /* [:NAME:]-X */ + } + } + return in; +} + +/* - regatom - the lowest level * * Optimization: gobbles an entire sequence of ordinary characters so that @@ -485,40 +603,22 @@ regatom(int *flagp) ret = regnode(ANY); *flagp |= HASWIDTH|SIMPLE; break; - case '[': { - register int clss; - register int classend; - - if (*regparse == '^') { /* Complement of range. */ - ret = regnode(ANYBUT); - regparse++; - } else - ret = regnode(ANYOF); - if (*regparse == ']' || *regparse == '-') - regc(*regparse++); - while (*regparse != '\0' && *regparse != ']') { - if (*regparse == '-') { - regparse++; - if (*regparse == ']' || *regparse == '\0') - regc('-'); - else { - clss = UCHARAT(regparse-2)+1; - classend = UCHARAT(regparse); - if (clss > classend+1) - FAIL("invalid [] range"); - for (; clss <= classend; clss++) - regc(clss); - regparse++; - } - } else - regc(*regparse++); - } - regc('\0'); - if (*regparse != ']') - FAIL("unmatched []"); + case '[': + if (*regparse == '^') { /* Complement of range. */ + ret = regnode(ANYBUT); regparse++; - *flagp |= HASWIDTH|SIMPLE; - } + } else + ret = regnode(ANYOF); + + regparse = regbracket(regparse); + if (regparse == NULL) + return(NULL); + + regc('\0'); + if (*regparse != ']') + FAIL("unmatched []"); + regparse++; + *flagp |= HASWIDTH|SIMPLE; break; case '(': ret = reg(1, &flags); @@ -701,8 +801,7 @@ STATIC int regrepeat(char *); #ifdef DEBUG int regnarrate = 0; -void regdump(); -STATIC char *regprop(); +STATIC constant char *regprop(constant char *); #endif /* @@ -726,16 +825,8 @@ regexec2(register regexp *prog, register constant char *string, int notbol) } /* If there is a "must appear" string, look for it. */ - if (prog->regmust != NULL) { - s = string; - while ((s = strchr(s, prog->regmust[0])) != NULL) { - if (strncmp(s, prog->regmust, prog->regmlen) == 0) - break; /* Found it. */ - s++; - } - if (s == NULL) /* Not present. */ - return(0); - } + if (prog->regmust != NULL && strstr(string, prog->regmust) == NULL) + return(0); /* Not present. */ /* Mark beginning of line for ^ . */ if (notbol) @@ -1068,14 +1159,11 @@ regnext(register char *p) #ifdef DEBUG -STATIC char *regprop(); - /* - regdump - dump a regexp onto stdout in vaguely comprehensible form */ void -regdump(r) -regexp *r; +regdump(regexp *r) { register char *s; register char op = EXACTLY; /* Arbitrary non-END op. */ @@ -1085,12 +1173,13 @@ regexp *r; s = r->program + 1; while (op != END) { /* While that wasn't END last time... */ op = OP(s); - printf("%2d%s", s-r->program, regprop(s)); /* Where, what. */ + /* prints ADDRESS:... where the ":..." is from regprop(s) */ + printf("%2ld%s", (long)(s - r->program), regprop(s)); next = regnext(s); if (next == NULL) /* Next ptr. */ printf("(0)"); else - printf("(%d)", (s-r->program)+(next-s)); + printf("(%ld)", (long)((s - r->program)+(next-s))); s += 3; if (op == ANYOF || op == ANYBUT || op == EXACTLY) { /* Literal string, where present. */ @@ -1117,8 +1206,7 @@ regexp *r; - regprop - printable representation of opcode */ static constant char * -regprop(op) -constant char *op; +regprop(constant char *op) { register char *p; static char buf[50]; @@ -15,7 +15,6 @@ typedef struct regexp { char regstart; /* Internal use only. */ char reganch; /* Internal use only. */ char *regmust; /* Internal use only. */ - int regmlen; /* Internal use only. */ char program[1]; /* Unwarranted chumminess with compiler. */ } regexp; @@ -31,4 +30,8 @@ extern int regexec2 _ANSI_ARGS_((regexp *prog, constant char *string, int notbol extern void regsub _ANSI_ARGS_((regexp *prog, constant char *source, char *dest)); extern void regerror _ANSI_ARGS_((constant char *msg)); +#ifdef DEBUG + extern void regdump _ANSI_ARGS_((regexp *r)); +#endif + #endif /* REGEXP */ @@ -75,6 +75,18 @@ extern int fd0; #if USE_TERMINFO #include <curses.h> #include <term.h> +#if HAVE_TPARM2 +#define LTPARM2(s,p1,p2) tparm(s, p1, p2) +#else +#if HAVE_TPARM8 +#define LTPARM2(s,p1,p2) tparm(s, p1, p2, 0, 0, 0, 0, 0, 0) +#else +#if HAVE_TPARM9 +#define LTPARM2(s,p1,p2) tparm(s, p1, p2, 0, 0, 0, 0, 0, 0, 0) +#else +#endif +#endif +#endif #else #if HAVE_NCURSESW_TERMCAP_H #include <ncursesw/termcap.h> @@ -254,6 +266,11 @@ static constant char *sc_init, /* Startup terminal initialization */ *sc_deinit; /* Exit terminal de-initialization */ +/* attrbits is the current attribute mode of the terminal + * (AT_UNDERLINE, AT_BOLD, AT_STANDOUT, AT_BLINK). + * attrmode is the user-defined mode, which may include AT_COLOR values, + * and the mapping of the AT_COLOR value may include the 4 attribute bits. */ +static int attrbits = 0; static int attrcolor = -1; #endif @@ -277,14 +294,15 @@ public int can_goto_line; /* Can move cursor to any line */ public int clear_bg; /* Clear fills with background color */ public lbool missing_cap = FALSE; /* Some capability is missing */ public constant char *kent = NULL; /* Keypad ENTER sequence */ +public lbool kent_mapped = FALSE; /* Keypad ENTER is mapped to a command */ public lbool term_addrs = FALSE; /* "ti" has been sent to terminal */ public lbool full_screen = TRUE; /* We're using all lines of terminal */ -static int attrmode = AT_NORMAL; +static int attrmode = AT_NORMAL; /* current attributes (AT_* bits) */ static int termcap_debug = -1; static int no_alt_screen; /* sc_init does not switch to alt screen */ extern int binattr; -extern int one_screen; +extern lbool one_screen; extern int shell_lines; #if !MSDOS_COMPILER @@ -295,15 +313,15 @@ static void tmodes(constant char *inti, constant char *outti, constant char *int extern int quiet; /* If VERY_QUIET, use visual bell for bell */ extern int no_vbell; -extern int no_back_scroll; +extern lbool no_back_scroll; extern int no_init; extern int no_keypad; extern int sigs; extern int top_scroll; extern int quit_if_one_screen; extern int oldbot; -extern int mousecap; -extern int is_tty; +extern int emouse; +extern lbool is_tty; extern int use_color; extern int no_paste; extern int wscroll; @@ -1285,6 +1303,10 @@ public constant char * special_key_str(int key) case SK_PAD_ZERO: s = ltgetstr("kpZRO", NULL, &sp); break; + case SK_PAD_ENTER: + s = kent; + kent_mapped = TRUE; + break; case SK_DELETE: s = ltgetstr("kdch1", "kD", &sp); if (s == NULL) @@ -1321,7 +1343,7 @@ public constant char * special_key_str(int key) static constant char *ltgoto(constant char *cap, int col, int line) { #if USE_TERMINFO - return tparm(cap, line, col); + return LTPARM2(cap, line, col); #else return tgoto(cap, col, line); #endif @@ -1352,7 +1374,7 @@ public void init_win_colors(void) /* * Get terminal capabilities via termcap. */ -public void get_term() +public void get_term(void) { termcap_debug = !isnullenv(lgetenv("LESS_TERMCAP_DEBUG")); #if MSDOS_COMPILER @@ -1655,7 +1677,7 @@ public void get_term() /* * Force repaint on any backward movement. */ - no_back_scroll = 1; + no_back_scroll = TRUE; } } #endif /* MSDOS_COMPILER */ @@ -1998,7 +2020,7 @@ public void term_init(void) } if (!no_keypad) ltputs(sc_s_keypad, sc_height, putchr); - if (mousecap) + if (emouse != 0) init_mouse(); if (no_paste) init_bracketed_paste(); @@ -2026,7 +2048,7 @@ public void term_init(void) win32_init_term(); term_addrs = TRUE; } - if (mousecap) + if (emouse != 0) init_mouse(); } @@ -2047,7 +2069,7 @@ public void term_deinit(void) #if !MSDOS_COMPILER if (!(quit_if_one_screen && one_screen)) { - if (mousecap) + if (emouse != 0) deinit_mouse(); if (no_paste) deinit_bracketed_paste(); @@ -2063,7 +2085,7 @@ public void term_deinit(void) win32_deinit_vt_term(); if (!(quit_if_one_screen && one_screen)) { - if (mousecap) + if (emouse != 0) deinit_mouse(); if (!no_init) win32_deinit_term(); @@ -2858,13 +2880,25 @@ static void tput_fmt(constant char *fmt, int color, int (*f_putc)(int)) static void tput_char_cattr(CHAR_ATTR cattr, int (*f_putc)(int)) { if (cattr & CATTR_UNDERLINE) + { ltputs(sc_u_in, 1, f_putc); + attrbits |= AT_UNDERLINE; + } if (cattr & CATTR_BOLD) + { ltputs(sc_b_in, 1, f_putc); + attrbits |= AT_BOLD; + } if (cattr & CATTR_BLINK) + { ltputs(sc_bl_in, 1, f_putc); + attrbits |= AT_BLINK; + } if (cattr & CATTR_STANDOUT) + { ltputs(sc_s_in, 1, f_putc); + attrbits |= AT_STANDOUT; + } } static void tput_color(constant char *str, int (*f_putc)(int)) @@ -2909,6 +2943,7 @@ static void tput_inmode(constant char *mode_str, int attr, int attr_bit, int (*f if (color_str == NULL || *color_str == '\0' || *color_str == '+') { ltputs(mode_str, 1, f_putc); + attrbits |= attr_bit; if (color_str == NULL || *color_str++ != '+') return; } @@ -2918,9 +2953,10 @@ static void tput_inmode(constant char *mode_str, int attr, int attr_bit, int (*f static void tput_outmode(constant char *mode_str, int attr_bit, int (*f_putc)(int)) { - if ((attrmode & attr_bit) == 0) + if ((attrbits & attr_bit) == 0) return; ltputs(mode_str, 1, f_putc); + attrbits &= ~attr_bit; } #else /* MSDOS_COMPILER */ @@ -3154,7 +3190,7 @@ static lbool win32_queued_char(void) /* * Push a char onto the back of the win32_queue. */ -static void win32_enqueue(int ch) +public void win32_enqueue(int ch) { WIN32_CHAR *wch = (WIN32_CHAR *) ecalloc(1, sizeof(WIN32_CHAR)); wch->wc_ch = ch; @@ -3194,6 +3230,12 @@ static int win32_get_queue(void) return ch; } +public void win32_clear_queue(void) +{ + while (win32_queued_char()) + (void) win32_get_queue(); +} + /* * Handle a mouse input event. */ @@ -3201,7 +3243,7 @@ static lbool win32_mouse_event(XINPUT_RECORD *xip) { char b; - if (!mousecap || xip->ir.EventType != MOUSE_EVENT) + if (emouse == 0 || xip->ir.EventType != MOUSE_EVENT) return (FALSE); /* Generate an X11 mouse sequence from the mouse event. */ @@ -3358,7 +3400,7 @@ static lbool win32_scan_code(XINPUT_RECORD *xip) /* * Handle a key input event. */ -static lbool win32_key_event(XINPUT_RECORD *xip) +static lbool win32_key_event(XINPUT_RECORD *xip, char *pch) { int repeat; char utf8[UTF8_MAX_LENGTH]; @@ -3379,9 +3421,19 @@ static lbool win32_key_event(XINPUT_RECORD *xip) return (FALSE); if (!xip->ir.Event.KeyEvent.bKeyDown) return (FALSE); - - if (win32_scan_code(xip)) + + /* + * If caller wants to see an immediate (unqueued) ASCII char from the + * keyboard, return it now. Otherwise queue the char for WIN32getch to read. + */ + if (pch != NULL && xip->ichar != '\0' && is_ascii_char(xip->ichar)) + { + *pch = (char) xip->ichar; return (TRUE); + } + + if (win32_scan_code(xip)) + return (pch == NULL); repeat = xip->ir.Event.KeyEvent.wRepeatCount; if (repeat > WIN32_MAX_REPEAT) @@ -3392,9 +3444,9 @@ static lbool win32_key_event(XINPUT_RECORD *xip) { constant char *p; for (p = utf8; p < up; ++p) - win32_enqueue(*p & 0xFF); + win32_enqueue((unsigned char) *p); } - return (TRUE); + return (pch == NULL); } /* @@ -3411,11 +3463,11 @@ static lbool win32_window_event(XINPUT_RECORD *xip) /* * Determine whether an input character is waiting to be read. */ -public lbool win32_kbhit2(lbool no_queued) +public lbool win32_kbhit2(char *pch) { XINPUT_RECORD xip; - if (!no_queued && win32_queued_char()) + if (pch == NULL && win32_queued_char()) return (TRUE); for (;;) @@ -3434,15 +3486,16 @@ public lbool win32_kbhit2(lbool no_queued) ReadConsoleInputW(tty, &xip.ir, 1, &nread); if (nread == 0) return (FALSE); - if (win32_mouse_event(&xip) || win32_key_event(&xip) || win32_window_event(&xip)) - break; + if (win32_key_event(&xip, pch)) + return (TRUE); + if (win32_mouse_event(&xip) || win32_window_event(&xip)) + return (pch == NULL); } - return (TRUE); } public lbool win32_kbhit(void) { - return win32_kbhit2(FALSE); + return win32_kbhit2(NULL); } /* @@ -29,6 +29,8 @@ extern int proc_backspace; extern int proc_return; extern int ctldisp; extern int status_col; +extern int status_line; +extern int hilite_target; extern void *ml_search; extern POSITION start_attnpos; extern POSITION end_attnpos; @@ -63,7 +65,6 @@ public POSITION osc8_uri_start = NULL_POSITION; public POSITION osc8_uri_end = NULL_POSITION; public POSITION osc8_text_start = NULL_POSITION; public POSITION osc8_text_end = NULL_POSITION; -char *osc8_path = NULL; char *osc8_uri = NULL; constant char *osc8_search_param = NULL; #endif @@ -230,8 +231,13 @@ public int get_cvt_ops(int search_type) { int ops = 0; - if (is_caseless && (!re_handles_caseless || (search_type & SRCH_NO_REGEX))) +#if RE_HANDLES_CASELESS + if (is_caseless && (search_type & SRCH_NO_REGEX)) ops |= CVT_TO_LC; +#else + if (is_caseless) + ops |= CVT_TO_LC; +#endif if (proc_backspace == OPT_ON || (bs_mode == BS_SPECIAL && proc_backspace == OPT_OFF)) ops |= CVT_BS; if (proc_return == OPT_ON || (bs_mode != BS_CONTROL && proc_backspace == OPT_OFF)) @@ -253,6 +259,14 @@ static lbool prev_pattern(struct pattern_info *info) return (info->text != NULL); } +/* + * Return text of previous search pattern. + */ +public constant char* prev_pattern_text(void) +{ + return search_info.text; +} + #if HILITE_SEARCH /* * Repaint the hilites currently displayed on the screen. @@ -300,6 +314,27 @@ public void repaint_hilite(lbool on) #endif /* + * Redraw the jump target line with the attn hilite on or off. + */ +public void draw_target_attn(lbool hilite) +{ + int sindex; + POSITION pos; + + if (!can_goto_line) /* {{ Are there any such terminals any more? }} */ + return; + if (squished) + return; + sindex = sindex_from_sline(jump_sline); + pos = position(sindex); + forw_line_seg(pos, chop_line() || hshift > 0, TRUE, FALSE, hilite && status_line, FALSE, NULL, NULL); + goto_line(sindex); + clear_eol(); + put_line_hilite(TRUE, hilite); + lower_left(); +} + +/* * Clear the attn hilite. */ public void clear_attn(void) @@ -312,6 +347,9 @@ public void clear_attn(void) POSITION epos; int moved = 0; + if (hilite_target) + draw_target_attn(FALSE); + if (start_attnpos == NULL_POSITION) return; old_start_attnpos = start_attnpos; @@ -962,7 +1000,7 @@ static void add_hilite(struct hilite_tree *anchor, struct hilite *hl) */ static void create_hilites(POSITION linepos, constant char *line, constant char *sp, constant char *ep, int attr, int *chpos) { - size_t start_index = ptr_diff(sp, line); /*{{type-issue}}*/ + size_t start_index = ptr_diff(sp, line); size_t end_index = ptr_diff(ep, line); struct hilite hl; size_t i; @@ -1818,6 +1856,7 @@ public lbool osc8_click(int sindex, int col) clickpos = pos_from_col(linepos, col, NULL_POSITION, -1); if (clickpos == NULL_POSITION) return FALSE; + linepos = beginning_of_line(linepos); if (forw_raw_line(linepos, &line, &line_len) == NULL_POSITION) return FALSE; r = osc8_search_line(SRCH_FORW|SRCH_OSC8, linepos, line, line_len, NULL, clickpos, &matches); @@ -1849,18 +1888,6 @@ static size_t scheme_length(constant char *uri, size_t uri_len) } /* - * Does a URI contain any dangerous characters? - */ -static lbool bad_uri(constant char *uri, size_t uri_len) -{ - size_t i; - for (i = 0; i < uri_len; i++) - if (strchr("'\"", uri[i]) != NULL) - return TRUE; - return FALSE; -} - -/* * Re-read the line containing the selected OSC8 link. */ static lbool osc8_read_selected(struct osc8_parse_info *op) @@ -1890,10 +1917,11 @@ public void osc8_open(void) char env_name[64]; size_t scheme_len; constant char *handler; - char *open_cmd; + char *cmd; + char *uri_q; size_t uri_len; - FILE *hf; - static constant char *env_name_pfx = "LESS_OSC8_"; + char *p; + static constant char *env_name_pfx = "LESS_OSC8_OPEN_"; if (osc8_linepos == NULL_POSITION) { @@ -1906,9 +1934,8 @@ public void osc8_open(void) return; } /* - * Read a "handler" shell cmd from environment variable "LESS_OSC8_scheme". - * pr_expand the handler cmd (to expand %o -> osc8_path) and execute it. - * Handler's stdout is an "opener" shell cmd; execute opener to open the link. + * Read a "handler" shell cmd from environment variable "LESS_OSC8_OPEN_scheme". + * Append the URI to the handler as an argument, and execute it. */ uri_len = ptr_diff(op.uri_end, op.uri_start); scheme_len = scheme_length(op.uri_start, uri_len); @@ -1923,16 +1950,19 @@ public void osc8_open(void) free(param); return; } -#if HAVE_POPEN - if (bad_uri(op.uri_start, uri_len)) + if (scheme_len == 0) { - error("Cannot open link containing quote characters", NULL_PARG); - return; + SNPRINTF1(env_name, sizeof(env_name), "%sNONE", env_name_pfx); + } else + { + SNPRINTF3(env_name, sizeof(env_name), "%s%.*s", env_name_pfx, (int) scheme_len, op.uri_start); + for (p = &env_name[strlen(env_name_pfx)]; *p != '\0'; p++) + if (ASCII_IS_UPPER(*p)) + *p = ASCII_TO_LOWER(*p); } - SNPRINTF3(env_name, sizeof(env_name), "%s%.*s", env_name_pfx, (int) scheme_len, op.uri_start); handler = lgetenv(env_name); if (isnullenv(handler) || strcmp(handler, "-") == 0) - handler = lgetenv("LESS_OSC8_ANY"); + handler = lgetenv("LESS_OSC8_OPEN_ANY"); if (isnullenv(handler)) { PARG parg; @@ -1940,31 +1970,25 @@ public void osc8_open(void) error("No handler for \"%s\" link type", &parg); return; } - /* {{ ugly global osc8_path }} */ - osc8_path = saven(op.uri_start, uri_len); - hf = popen(pr_expand(handler), "r"); - free(osc8_path); - osc8_path = NULL; - if (hf == NULL) - { - PARG parg; - parg.p_string = env_name; - error("Cannot execute protocol handler in %s", &parg); - return; - } - open_cmd = readfd(hf); - pclose(hf); - if (strncmp(open_cmd, ":e", 2) == 0) + uri_q = shell_quoten(op.uri_start, uri_len); + cmd = ecalloc(strlen(handler) + strlen(uri_q) + 2, sizeof(char)); + sprintf(cmd, "%s %s", handler, uri_q); + free(uri_q); { - edit(skipsp(&open_cmd[2])); - } else - { - lsystem(open_cmd, "link done"); + constant char *exec_cmd = cmd; + constant char *done_msg = "link done"; + POSITION save_osc8_linepos = osc8_linepos; + if (*exec_cmd == CONTROL('P')) + { + done_msg = NULL; + exec_cmd++; + } + lsystem(exec_cmd, done_msg); + /* lsystem reedits the input file which clears the selected + * OSC8 link, so restore it. */ + osc8_linepos = save_osc8_linepos; } - free(open_cmd); -#else - error("Cannot open link because your system does not support popen", NULL_PARG); -#endif /* HAVE_POPEN */ + free(cmd); } /* @@ -2026,15 +2050,19 @@ public void chg_caseless(void) * If regex handles caseless, we need to discard * the pattern which was compiled with the old caseless. */ - if (!re_handles_caseless) - /* We handle caseless, so the pattern doesn't change. */ - return; +#if !RE_HANDLES_CASELESS + /* Less handles caseless, so the pattern doesn't change. */ + return; +#endif } /* * Regenerate the pattern using the new state. */ - clear_pattern(&search_info); - (void) hist_pattern(search_info.search_type); + if (prev_pattern(&search_info)) + { + clear_pattern(&search_info); + (void) hist_pattern(search_info.search_type); + } } /* @@ -321,8 +321,14 @@ static enum tag_result findctag(constant char *tag) * First see if it is a line number. */ tagendline = FALSE; - if (getnum(&p, NULL, FALSE, &n)) + if (getnum(&p, NULL, FALSE, &n)) { + /* + * Line numbers start from 1. + */ + if (n == 0) + continue; taglinenum = n; + } else { /* @@ -274,5 +274,5 @@ public int getchr(void) c = '\340'; } while (result != 1); - return (c & 0xFF); + return (unsigned char) c; } diff --git a/version.c b/version.c index b3d83c1ca2fc..5d03b1350218 100644 --- a/version.c +++ b/version.c @@ -1077,7 +1077,40 @@ v691 1/10/26 Fix mingw build. v692 1/29/26 Fix memory leak in setupterm; clear termio ICRNL|INLCR; fix bug with negative value in -z; fix bug with empty terminfo caps; make lesstest ignore nl_langinfo; - revert HOME/END to g/G; add keys & cmds to lesskey parser. + revert HOME/END to g/G; add keys & cmds to lesskey parser. +v693 2/14/26 Fix binary file with redirected stdout; fix error messages + with redirected stdout; fix buffer overrun with malformed + lesskey file; fix bad scrolling past EOF; fix command + parser bugs; fix -D bug when no color specified; add -DT; + make -w/-W hilite on backward movement; show pattern in + "not found" message. +v694 3/24/26 | cmd pipes 1 line if mark is top line; allow numeric arg + on m/M cmds; support POSIX char classes with built-in regex; + don't retry read after error; fix crash with bad tags file; + add --past-eof; add --emouse; fix restore mark if not at top; + don't save cleared marks. +v695 4/3/26 Fix build if tparm doesn't use varargs; fix prompt overflow + with & filtering; fix hilite when change -i with & filtering; + add --end-prompt; install lessecho in libexecdir; change mark + cmds to take file line number not screen line; add numeric + arg to ' cmd; add %O and ?o to prompts; fix + --show-preproc-error with some shells. +v696 4/3/26 Doc. +v697 4/19/26 Fix bug using PCRE2 with more than 5 parentheses; discard + pending keys when interrupt with ^X; fix bad display with + LESS_LINES. +v698 4/23/26 Fix bad display after message in narrow terminal; replace + LESS_OSC8_xxx with LESS_OSC8_OPEN_xxx; add \kpe to lesskey. +v699 4/23/26 Add less-osc8-*.bash files to distribution. +v700 4/30/26 Add \kpe to lesskey; improve less-osc8-* scripts. +v701 5/13/26 Replace less-osc-*.bash with less-osc8-open.sh; don't init + terminal if stdout is not tty; fix bug clicking OSC 8 link + in a long line; fix misread chars on Windows; remove %O. +v702 5/22/26 Doc. +v703 5/30/26 Fix handling unsafe man options in OSC 8 link; fix unsafe + handling of unterminated OSC seq; shell-escape expansion + of % and #. +v704 5/30/26 Fix uninstall target in Makefile. */ -char version[] = "692"; +char version[] = "704"; |
