Vendor import of less v590.

This commit is contained in:
Xin LI 2021-07-17 22:00:54 -07:00
parent bb457ab744
commit 1f8b3bb911
49 changed files with 1572 additions and 1099 deletions

View File

@ -7,6 +7,7 @@ GIT = git
NROFF = nroff -t -man
srcdir = .
REL := $(shell sed -e '/char version/!d' -e 's/[^0-9.]*\([0-9.]*\).*/\1/' -e q ${srcdir}/version.c)
ifeq ($(USE_PYTHON),1)
MKHELP = mkhelp.py
@ -22,7 +23,7 @@ SRC = \
help.c ifile.c input.c jump.c line.c linenum.c \
lsystem.c mark.c optfunc.c option.c opttbl.c os.c \
output.c pattern.c position.c prompt.c search.c signal.c \
tags.c ttyin.c version.c
tags.c ttyin.c version.c xbuf.c
DISTFILES_W = \
defines.ds Makefile.dsb Makefile.dsg Makefile.dsu \
defines.o2 Makefile.o2e \
@ -34,9 +35,9 @@ UNICODE_FILES = \
DISTFILES = \
${SRC} regexp.c regexp.h \
COPYING INSTALL LICENSE Makefile.in Makefile.aut NEWS README \
configure.ac lesskey.c lessecho.c scrsize.c \
configure.ac lesskey.c lesskey_parse.c lessecho.c scrsize.c \
charset.h cmd.h funcs.h lglob.h less.h lesskey.h option.h \
pckeys.h pattern.h position.h \
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.hlp \
@ -48,6 +49,7 @@ DISTFILES = \
all: help.c funcs.h $(UNICODE_FILES) ${srcdir}/configure
release: .FORCE
@if grep -s 'Major changes between .*${REL}' NEWS ; then :; else echo '*** NEWS is not updated for ${REL}'; exit 1; fi
${MAKE} -f Makefile.aut tagall
${MAKE} -f Makefile.aut all
${MAKE} -f Makefile.aut clean
@ -75,26 +77,19 @@ lint:
clean:
rm -f Makefile config.status config.log config.cache defines.h stamp-h \
configure defines.h.in funcs.h help.c \
README NEWS \
less.nro less.man lesskey.nro lesskey.man lessecho.nro lessecho.man
distclean: clean
realclean: clean
REPLACE_VERSION = \
@REL=`sed -e '/char version/!d' -e 's/[^0-9.]*\([0-9.]*\).*/\1/' -e q ${srcdir}/version.c`; \
DT=`date '+%d %h %Y'`; \
echo "Stuffing version number $$REL into $@"; \
echo "Stuffing version number ${REL} into $@"; \
rm -f $@; \
sed \
-e "s;@@VERSION@@;$$REL;" \
-e "s;@@DATE@@;$$DT;" \
-e "s;@@HOMEPAGE@@;${HOMEPAGE};" >$@
-e "s;@@VERSION@@;${REL};" \
-e "s;@@DATE@@;$$DT;" >$@
${srcdir}/README: ${srcdir}/README.VER ${srcdir}/version.c
${REPLACE_VERSION} ${srcdir}/README.VER
${srcdir}/NEWS: ${srcdir}/NEWS.VER ${srcdir}/version.c
${REPLACE_VERSION} ${srcdir}/NEWS.VER
${srcdir}/less.nro: ${srcdir}/less.nro.VER ${srcdir}/version.c
${REPLACE_VERSION} ${srcdir}/less.nro.VER
${srcdir}/lesskey.nro: ${srcdir}/lesskey.nro.VER ${srcdir}/version.c
@ -127,27 +122,36 @@ unicode/EastAsianWidth.txt:
distfiles: ${DISTFILES}
echo_distfiles:
echo ${DISTFILES}
dist: ${DISTFILES}
if [ ! -d ${srcdir}/release ]; then mkdir ${srcdir}/release; fi
@cd ${srcdir}; \
REL=`sed -e '/char version/!d' -e 's/[^0-9.]*\([0-9.]*\).*/less-\1/' -e q version.c`; \
rm -rf release/$$REL; mkdir release/$$REL; \
echo "Preparing $$REL"; \
rm -rf $$REL; mkdir $$REL; \
for file in ${DISTFILES}; do \
./add_copyright $$file $$REL; \
done; \
cd $$REL; chmod -w *; chmod +w ${DISTFILES_W}; chmod +x configure; cd ..; \
echo "Creating release/$$REL/$$REL.tar.gz"; \
tar -cf - $$REL | gzip -c >release/$$REL/$$REL.tar.gz; \
echo "Signing release/$$REL/$$REL.tar.gz"; \
gpg --detach-sign release/$$REL/$$REL.tar.gz; \
mv release/$$REL/$$REL.tar.gz.sig release/$$REL/$$REL.sig; \
echo "Creating release/$$REL/$$REL.zip"; \
zip -rq release/$$REL/$$REL.zip $$REL; \
rm -rf $$REL
@LESSREL=less-${REL} && RELDIR=release/$$LESSREL && \
cd ${srcdir} && \
rm -rf $$RELDIR && mkdir $$RELDIR && \
echo "Preparing $$LESSREL" && \
rm -rf $$LESSREL && mkdir $$LESSREL && \
cp ${DISTFILES} $$LESSREL && \
cd $$LESSREL && chmod -w * && chmod +w ${DISTFILES_W} && chmod +x configure && cd .. && \
echo "Creating $$RELDIR/${REL}.tar.gz" && \
tar -cf - $$LESSREL | gzip -c >$$RELDIR/$$LESSREL.tar.gz && \
echo "Signing $$RELDIR/$$LESSREL.tar.gz" && \
gpg --detach-sign $$RELDIR/$$LESSREL.tar.gz && \
mv $$RELDIR/$$LESSREL.tar.gz.sig $$RELDIR/$$LESSREL.sig && \
echo "Creating $$RELDIR/$$LESSREL.zip" && \
zip -rq $$RELDIR/$$LESSREL.zip $$LESSREL && \
rm -rf $$LESSREL
tagall:
@REL=`sed -e '/char version/!d' -e 's/[^0-9.]*\([0-9.]*\).*/v\1/' -e q ${srcdir}/version.c`; \
echo "tagging $$REL"; \
$(GIT) tag -a -f -m "$$REL" "$$REL"
echo "tagging v${REL}"; \
$(GIT) tag -a -f -m "v${REL}" "v${REL}"
gnu_upload:
@if [ -z "${REL}" ]; then echo "Please set REL=nnn"; exit 1; fi; \
if [ ! -s release/less-${REL}/less-${REL}.tar.gz ]; then echo "release/less-${REL}/less-${REL}.tar.gz does not exist"; exit 1; fi; \
cd release/less-${REL} && \
gpg -b less-${REL}.tar.gz && \
( echo "version: 1.2"; echo "directory: less"; echo "filename: less-${REL}.tar.gz" ) > less-${REL}.tar.gz.directive && \
gpg --clearsign less-${REL}.tar.gz.directive
@echo "upload ready: cd release/less-${REL}; ftp ftp-upload.gnu.org; cd /incoming/ftp; put less-${REL}.tar.gz less-${REL}.tar.gz.sig less-${REL}.tar.gz.directive.asc"

View File

@ -21,10 +21,10 @@ EXT = .EXE
OBJ = \
main.obj screen.obj brac.obj ch.obj charset.obj cmdbuf.obj \
command.obj cvt.obj decode.obj edit.obj filename.obj forwback.obj \
help.obj ifile.obj input.obj jump.obj line.obj linenum.obj \
help.obj ifile.obj input.obj jump.obj lesskey_parse.obj line.obj linenum.obj \
lsystem.obj mark.obj optfunc.obj option.obj opttbl.obj os.obj \
output.obj pattern.obj position.obj prompt.obj search.obj signal.obj \
tags.obj ttyin.obj version.obj
tags.obj ttyin.obj version.obj xbuf.obj
all: less$(EXT) lesskey$(EXT)
@ -35,8 +35,8 @@ less$(EXT): $(OBJ)
$(CC) $(LDFLAGS) -e$@ *.obj $(LIBS)
ren lesskey.obo lesskey.obj
lesskey$(EXT): lesskey.obj version.obj
$(CC) $(LDFLAGS) -e$@ lesskey.obj version.obj $(LIBS)
lesskey$(EXT): lesskey.obj lesskey_parse.obj version.obj xbuf.obj
$(CC) $(LDFLAGS) -e$@ lesskey.obj lesskey_parse.obj version.obj xbuf.obj $(LIBS)
defines.h: defines.ds
-del defines.h

View File

@ -36,18 +36,18 @@ manext = 1
OBJ = \
main.${O} screen.${O} brac.${O} ch.${O} charset.${O} cmdbuf.${O} \
command.${O} cvt.${O} decode.${O} edit.${O} filename.${O} forwback.${O} \
help.${O} ifile.${O} input.${O} jump.${O} line.${O} linenum.${O} \
help.${O} ifile.${O} input.${O} jump.${O} lesskey_parse.${O} line.${O} linenum.${O} \
lsystem.${O} mark.${O} optfunc.${O} option.${O} opttbl.${O} os.${O} \
output.${O} pattern.${O} position.${O} prompt.${O} search.${O} signal.${O} \
tags.${O} ttyin.${O} version.${O}
tags.${O} ttyin.${O} version.${O} xbuf.${O}
all: less lesskey lessecho
less: ${OBJ}
${CC} ${LDFLAGS} -o $@ ${OBJ} ${LIBS}
lesskey: lesskey.${O} version.${O}
${CC} ${LDFLAGS} -o $@ lesskey.${O} version.${O}
lesskey: lesskey.${O} lesskey_parse.${O} version.${O} xbuf.${O}
${CC} ${LDFLAGS} -o $@ lesskey.${O} lesskey_parse.${O} version.${O} xbuf.${O}
lessecho: lessecho.${O} version.${O}
${CC} ${LDFLAGS} -o $@ lessecho.${O} version.${O}

View File

@ -30,10 +30,10 @@ LIBS = $(LIBDIR)\llibce.lib $(LIBDIR)\graphics.lib
OBJ = \
main.obj screen.obj brac.obj ch.obj charset.obj cmdbuf.obj \
command.obj cvt.obj decode.obj edit.obj filename.obj forwback.obj \
help.obj ifile.obj input.obj jump.obj line.obj linenum.obj \
help.obj ifile.obj input.obj jump.obj lesskey_parse.obj line.obj linenum.obj \
lsystem.obj mark.obj optfunc.obj option.obj opttbl.obj os.obj \
output.obj pattern.obj position.obj prompt.obj search.obj signal.obj \
tags.obj ttyin.obj version.obj
tags.obj ttyin.obj version.obj xbuf.obj
all: less lesskey
@ -43,8 +43,8 @@ less: $(OBJ)
-if exist lesskey.obj del lesskey.obj
$(CC) $(LDFLAGS) -o $@ *.obj $(LIBS)
lesskey: lesskey.obj version.obj
$(CC) $(LDFLAGS) -o $@ lesskey.obj version.obj $(LIBS)
lesskey: lesskey.obj lesskey_parse.obj version.obj xbuf.obj
$(CC) $(LDFLAGS) -o $@ lesskey.obj lesskey_parse.obj version.obj xbuf.obj $(LIBS)
defines.h: defines.ds
-del defines.h

View File

@ -46,18 +46,23 @@ SHELL = /bin/sh
OBJ = \
main.${O} screen.${O} brac.${O} ch.${O} charset.${O} cmdbuf.${O} \
command.${O} cvt.${O} decode.${O} edit.${O} filename.${O} forwback.${O} \
help.${O} ifile.${O} input.${O} jump.${O} line.${O} linenum.${O} \
help.${O} ifile.${O} input.${O} jump.${O} \
line.${O} linenum.${O} \
lsystem.${O} mark.${O} optfunc.${O} option.${O} opttbl.${O} os.${O} \
output.${O} pattern.${O} position.${O} prompt.${O} search.${O} signal.${O} \
tags.${O} ttyin.${O} version.${O} @REGEX_O@
tags.${O} ttyin.${O} version.${O} xbuf.${O} @REGEX_O@
ifneq (@SECURE_COMPILE@,1)
OBJ += lesskey_parse.${O}
endif
all: less$(EXEEXT) lesskey$(EXEEXT) lessecho$(EXEEXT)
less$(EXEEXT): ${OBJ}
${CC} ${LDFLAGS} -o $@ ${OBJ} ${LIBS}
lesskey$(EXEEXT): lesskey.${O} version.${O}
${CC} ${LDFLAGS} -o $@ lesskey.${O} version.${O}
lesskey$(EXEEXT): lesskey.${O} lesskey_parse.${O} xbuf.${O} version.${O}
${CC} ${LDFLAGS} -o $@ lesskey.${O} lesskey_parse.${O} xbuf.${O} version.${O}
lessecho$(EXEEXT): lessecho.${O} version.${O}
${CC} ${LDFLAGS} -o $@ lessecho.${O} version.${O}

View File

@ -21,18 +21,18 @@ O = obj
OBJ = \
main.${O} screen.${O} brac.${O} ch.${O} charset.${O} cmdbuf.${O} \
command.${O} cvt.${O} decode.${O} edit.${O} filename.${O} forwback.${O} \
help.${O} ifile.${O} input.${O} jump.${O} line.${O} linenum.${O} \
help.${O} ifile.${O} input.${O} jump.${O} lesskey_parse.${O} line.${O} linenum.${O} \
lsystem.${O} mark.${O} optfunc.${O} option.${O} opttbl.${O} os.${O} \
output.${O} pattern.${O} position.${O} prompt.${O} search.${O} signal.${O} \
tags.${O} ttyin.${O} version.${O} regexp.${O}
tags.${O} ttyin.${O} version.${O} xbuf.${O} regexp.${O}
all: less.exe lesskey.exe scrsize.exe
less.exe: ${OBJ}
${CC} ${OBJ} -o $@ ${LDFLAGS} ${LIBS}
lesskey.exe: lesskey.${O} version.${O}
${CC} lesskey.${O} version.${O} -o $@ ${LDFLAGS}
lesskey.exe: lesskey.${O} lesskey_parse.${O} version.${O} xbuf.${O}
${CC} lesskey.${O} lesskey_parse.${O} version.${O} xbuf.${O} -o $@ ${LDFLAGS}
scrsize.exe: scrsize.c
${CC} ${CFLAGS} -D__ST_MT_ERRNO__ -s -Zmtd -lX11 $<

View File

@ -25,18 +25,18 @@ O = r
OBJ = \
main.${O} screen.${O} brac.${O} ch.${O} charset.${O} cmdbuf.${O} \
command.${O} cvt.${O} decode.${O} edit.${O} filename.${O} forwback.${O} \
help.${O} ifile.${O} input.${O} jump.${O} line.${O} linenum.${O} \
help.${O} ifile.${O} input.${O} jump.${O} lesskey_parse.${O} line.${O} linenum.${O} \
lsystem.${O} mark.${O} optfunc.${O} option.${O} opttbl.${O} os.${O} \
output.${O} pattern.${O} position.${O} prompt.${O} search.${O} signal.${O} \
tags.${O} ttyin.${O} version.${O} regexp.${O}
tags.${O} ttyin.${O} version.${O} xbuf.${O} regexp.${O}
all: less lessecho lesskey
less: ${OBJ}
${CC} ${OBJ} -f=$@ ${LDFLAGS} ${LIBS}
lesskey: lesskey.${O} version.${O}
${CC} lesskey.${O} version.${O} -f=$@ ${LDFLAGS}
lesskey: lesskey.${O} lesskey_parse.${O} version.${O} xbuf.${O}
${CC} lesskey.${O} lesskey_parse.${O} version.${O} xbuf.${O} -f=$@ ${LDFLAGS}
lessecho: lessecho.${O} version.${O}
${CC} lessecho.${O} version.${O} -f=$@ ${LDFLAGS}

View File

@ -24,18 +24,18 @@ O = r
OBJ = \
main.${O} screen.${O} brac.${O} ch.${O} charset.${O} cmdbuf.${O} \
command.${O} cvt.${O} decode.${O} edit.${O} filename.${O} forwback.${O} \
help.${O} ifile.${O} input.${O} jump.${O} line.${O} linenum.${O} \
help.${O} ifile.${O} input.${O} jump.${O} lesskey_parse.${O} line.${O} linenum.${O} \
lsystem.${O} mark.${O} optfunc.${O} option.${O} opttbl.${O} os.${O} \
output.${O} pattern.${O} position.${O} prompt.${O} search.${O} signal.${O} \
tags.${O} ttyin.${O} version.${O} regexp.${O}
tags.${O} ttyin.${O} version.${O} xbuf.${O} regexp.${O}
all: less lesskey
less: ${OBJ}
${CC} ${OBJ} -f=$@ ${LDFLAGS} ${LIBS}
lesskey: lesskey.${O} version.${O}
${CC} lesskey.${O} version.${O} -f=$@ ${LDFLAGS}
lesskey: lesskey.${O} lesskey_parse.${O} version.${O} xbuf.${O}
${CC} lesskey.${O} lesskey_parse.${O} version.${O} xbuf.${O} -f=$@ ${LDFLAGS}
${OBJ}: defines.h less.h

View File

@ -28,10 +28,10 @@ LIBS = ${LIBDIR}\import32.lib ${LIBDIR}\cw32.lib
OBJ = \
main.obj screen.obj brac.obj ch.obj charset.obj cmdbuf.obj \
command.obj cvt.obj decode.obj edit.obj filename.obj forwback.obj \
help.obj ifile.obj input.obj jump.obj line.obj linenum.obj \
help.obj ifile.obj input.obj jump.obj lesskey_parse.obj line.obj linenum.obj \
lsystem.obj mark.obj optfunc.obj option.obj opttbl.obj os.obj \
output.obj pattern.obj position.obj prompt.obj search.obj signal.obj \
tags.obj ttyin.obj version.obj regexp.obj
tags.obj ttyin.obj version.obj xbuf.obj regexp.obj
all: less lesskey lessecho
@ -42,7 +42,7 @@ all: less lesskey lessecho
less: ${OBJ}
${LD} ${LDFLAGS} ${LIBDIR}\c0x32.obj $**, $@,,${LIBS}
lesskey: lesskey.obj version.obj
lesskey: lesskey.obj lesskey_parse.obj version.obj xbuf.obj
${LD} ${LDFLAGS} ${LIBDIR}\c0x32.obj $**, $@,,${LIBS}
lessecho: lessecho.obj version.obj

View File

@ -81,7 +81,7 @@ LESS_SRC = brac.c ch.c charset.c cmdbuf.c command.c \
lsystem.c main.c mark.c optfunc.c option.c \
opttbl.c os.c output.c pattern.c position.c \
prompt.c screen.c scrsize.c search.c \
signal.c tags.c ttyin.c version.c
signal.c tags.c ttyin.c version.c xbuf.c
ifeq (${REGEX_PACKAGE},regcomp-local)
LESS_SRC += regexp.c
endif
@ -89,10 +89,10 @@ endif
OBJ = \
main.o screen.o brac.o ch.o charset.o cmdbuf.o \
command.o cvt.o decode.o edit.o filename.o forwback.o \
help.o ifile.o input.o jump.o line.o linenum.o \
help.o ifile.o input.o jump.o lesskey_parse.o line.o linenum.o \
lsystem.o mark.o optfunc.o option.o opttbl.o os.o \
output.o pattern.o position.o prompt.o search.o signal.o \
tags.o ttyin.o version.o
tags.o ttyin.o version.o xbuf.o
ifeq (${REGEX_PACKAGE},regcomp-local)
OBJ += regexp.o
endif
@ -103,8 +103,8 @@ all: clean less lesskey lessecho
less: ${OBJ}
${CC} ${LDFLAGS} -o $@ ${OBJ} ${LIBS}
lesskey: lesskey.o version.o
${CC} ${LDFLAGS} -o $@ lesskey.o version.o
lesskey: lesskey.o lesskey_parse.o version.o xbuf.o
${CC} ${LDFLAGS} -o $@ lesskey.o lesskey_parse.o version.o xbuf.o
lessecho: lessecho.o version.o
${CC} ${LDFLAGS} -o $@ lessecho.o version.o

View File

@ -26,18 +26,18 @@ LIBS = user32.lib
OBJ = \
main.obj screen.obj brac.obj ch.obj charset.obj cmdbuf.obj \
command.obj cvt.obj decode.obj edit.obj filename.obj forwback.obj \
help.obj ifile.obj input.obj jump.obj line.obj linenum.obj \
help.obj ifile.obj input.obj jump.obj lesskey_parse.obj line.obj linenum.obj \
lsystem.obj mark.obj optfunc.obj option.obj opttbl.obj os.obj \
output.obj pattern.obj position.obj prompt.obj search.obj signal.obj \
tags.obj ttyin.obj version.obj regexp.obj
tags.obj ttyin.obj version.obj xbuf.obj regexp.obj
all: less.exe lesskey.exe
less.exe: $(OBJ)
$(LD) $(LDFLAGS) $** $(LIBS) /out:$@
lesskey.exe: lesskey.obj version.obj
$(LD) $(LDFLAGS) lesskey.obj version.obj $(LIBS) /out:$@
lesskey.exe: lesskey.obj lesskey_parse.obj version.obj xbuf.obj
$(LD) $(LDFLAGS) lesskey.obj lesskey_parse.obj version.obj xbuf.obj $(LIBS) /out:$@
defines.h: defines.wn
-del defines.h

30
NEWS
View File

@ -3,8 +3,7 @@
======================================================================
For the latest news about less, see the "less" Web page:
https://greenwoodsoftware.com/less
For the latest news about less, see https://greenwoodsoftware.com/less
You can also download the latest version of less from there.
Report bugs, suggestions or comments at
@ -12,7 +11,32 @@
======================================================================
Major changes between "less" versions 563 and 581.2
Major changes between "less" versions 581 and 590
* Make less able to read lesskey source files (deprecating lesskey).
* If XDG_CONFIG_HOME is set, find lesskey source file
in $XDG_CONFIG_HOME/lesskey rather than $HOME/.lesskey.
* If XDG_DATA_HOME is set, find and store history file
in $XDG_DATA_HOME/lesshst rather than $HOME/.lesshst.
* Add the --lesskey-src option.
* Add the --file-size option.
* With -F, if screen is resized to make file fit on one screen, don't exit.
* Fix bug which could leave terminal in mouse-reporting mode
after exiting less.
* Fix bug which caused failure to respond to window resize.
* Fix backslash bug searching in tag file.
======================================================================
Major changes between "less" versions 563 and 581
* Change ESC-u command to toggle, not disable, highlighting per man page.

9
README
View File

@ -1,7 +1,5 @@
Less, version 581.2
This is the distribution of less, version 581.2, released 28 Apr 2021.
This is the source code distribution of "less".
This program is part of the GNU project (http://www.gnu.org).
This program is free software. You may redistribute it and/or
@ -19,6 +17,11 @@
=========================================================================
You should build from a clone of a git repository
ONLY IF you are doing development on the less source itself.
If you are merely using less as a tool, you should download a release
from http://greenwoodsoftware.com and NOT from github.
The formatted manual page is in less.man.
The manual page nroff source is in less.nro.
Major changes made since the last posted version are in NEWS.

2
ch.c
View File

@ -860,7 +860,7 @@ ch_init(f, flags)
* Allocate and initialize a new filestate.
*/
thisfile = (struct filestate *)
calloc(1, sizeof(struct filestate));
ecalloc(1, sizeof(struct filestate));
thisfile->buflist.next = thisfile->buflist.prev = END_OF_CHAIN;
thisfile->nbufs = 0;
thisfile->flags = flags;

View File

@ -1401,11 +1401,12 @@ mlist_size(ml)
* Get the name of the history file.
*/
static char *
histfile_name(VOID_PARAM)
histfile_name(must_exist)
int must_exist;
{
char *home;
char *xdg;
char *name;
int len;
/* See if filename is explicitly specified by $LESSHISTFILE. */
name = lgetenv("LESSHISTFILE");
@ -1421,19 +1422,25 @@ histfile_name(VOID_PARAM)
if (strcmp(LESSHISTFILE, "") == 0 || strcmp(LESSHISTFILE, "-") == 0)
return (NULL);
/* Otherwise, file is in $HOME. */
/* Try in $XDG_DATA_HOME first, then in $HOME. */
xdg = lgetenv("XDG_DATA_HOME");
home = lgetenv("HOME");
if (isnullenv(home))
{
#if OS2
if (isnullenv(home))
home = lgetenv("INIT");
if (isnullenv(home))
#endif
return (NULL);
name = NULL;
if (!must_exist)
{
/* If we're writing the file and the file already exists, use it. */
name = dirfile(xdg, &LESSHISTFILE[1], 1);
if (name == NULL)
name = dirfile(home, LESSHISTFILE, 1);
}
len = (int) (strlen(home) + strlen(LESSHISTFILE) + 2);
name = (char *) ecalloc(len, sizeof(char));
SNPRINTF2(name, len, "%s/%s", home, LESSHISTFILE);
if (name == NULL)
name = dirfile(xdg, &LESSHISTFILE[1], must_exist);
if (name == NULL)
name = dirfile(home, LESSHISTFILE, must_exist);
return (name);
}
@ -1454,7 +1461,7 @@ read_cmdhist2(action, uparam, skip_search, skip_shell)
char *p;
int *skip = NULL;
filename = histfile_name();
filename = histfile_name(1);
if (filename == NULL)
return;
f = fopen(filename, "r");
@ -1700,7 +1707,7 @@ save_cmdhist(VOID_PARAM)
if (!histfile_modified())
return;
histname = histfile_name();
histname = histfile_name(0);
if (histname == NULL)
return;
tempname = make_tempname(histname);

View File

@ -791,6 +791,7 @@ prompt(VOID_PARAM)
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 */
#if MSDOS_COMPILER==WIN32C
/*

5
configure vendored
View File

@ -622,6 +622,7 @@ ac_includes_default="\
ac_subst_vars='LTLIBOBJS
LIBOBJS
REGEX_O
SECURE_COMPILE
INSTALL_DATA
INSTALL_SCRIPT
INSTALL_PROGRAM
@ -5269,9 +5270,13 @@ fi
if test "${with_secure+set}" = set; then :
withval=$with_secure; $as_echo "#define SECURE_COMPILE 1" >>confdefs.h
SECURE_COMPILE=1
else
$as_echo "#define SECURE_COMPILE 0" >>confdefs.h
SECURE_COMPILE=0
fi

View File

@ -387,7 +387,9 @@ fi
# Compile in secure mode?
AC_ARG_WITH(secure,
[ --with-secure Compile in secure mode],
AC_DEFINE(SECURE_COMPILE, 1), AC_DEFINE(SECURE_COMPILE, 0))
AC_DEFINE(SECURE_COMPILE, 1)
AC_SUBST(SECURE_COMPILE,1), AC_DEFINE(SECURE_COMPILE, 0)
AC_SUBST(SECURE_COMPILE,0))
# Should we use floating point?
AC_MSG_CHECKING(for floating point)
@ -595,7 +597,7 @@ AH_TOP([
* PIPEC is 1 if you wish to have the "|" command
* which allows the user to pipe data into a shell command.
*/
#define PIPEC (!SECURE)
#define PIPEC (!SECURE && HAVE_POPEN)
/*
* LOGFILE is 1 if you wish to allow the -o option (to create log files).
@ -627,6 +629,7 @@ AH_TOP([
#define LESSKEYFILE ".less"
#define LESSKEYFILE_SYS SYSDIR "/sysless"
#define DEF_LESSKEYINFILE ".lesskey"
#define LESSKEYINFILE_SYS SYSDIR "/syslesskey"
#define LESSHISTFILE ".lesshst"
@ -699,6 +702,9 @@ AH_TOP([
/* Define to 1 if you have the strstr() function. */
#define HAVE_STRSTR 1
/* Define to 1 to support reading lesskey source files (not just binary). */
#define HAVE_LESSKEYSRC 1
/*
* Sizes of various buffers.
*/

View File

@ -339,21 +339,41 @@ init_cmds(VOID_PARAM)
add_fcmd_table((char*)cmdtable, sizeof(cmdtable));
add_ecmd_table((char*)edittable, sizeof(edittable));
#if USERFILE
/*
* For backwards compatibility,
* try to add tables in the OLD system lesskey file.
*/
#ifdef BINDIR
add_hometable(NULL, BINDIR "/.sysless", 1);
#ifdef BINDIR /* For backwards compatibility */
/* Try to add tables in the OLD system lesskey file. */
add_hometable(lesskey, NULL, BINDIR "/.sysless", 1);
#endif
/*
* Try to add the tables in the system lesskey file.
* Try to load lesskey source file or binary file.
* If the source file succeeds, don't load binary file.
* The binary file is likely to have been generated from
* a (possibly out of date) copy of the src file,
* so loading it is at best redundant.
*/
add_hometable("LESSKEY_SYSTEM", LESSKEYFILE_SYS, 1);
/*
* Try to add the tables in the standard lesskey file "$HOME/.less".
* Try to add tables in system lesskey src file.
*/
add_hometable("LESSKEY", LESSKEYFILE, 0);
#if HAVE_LESSKEYSRC
if (add_hometable(lesskey_src, "LESSKEYIN_SYSTEM", LESSKEYINFILE_SYS, 1) != 0)
#endif
{
/*
* Try to add the tables in the system lesskey binary file.
*/
add_hometable(lesskey, "LESSKEY_SYSTEM", LESSKEYFILE_SYS, 1);
}
/*
* Try to add tables in the lesskey src file "$HOME/.lesskey".
*/
#if HAVE_LESSKEYSRC
if (add_hometable(lesskey_src, "LESSKEYIN", DEF_LESSKEYINFILE, 0) != 0)
#endif
{
/*
* Try to add the tables in the standard lesskey binary file "$HOME/.less".
*/
add_hometable(lesskey, "LESSKEY", LESSKEYFILE, 0);
}
#endif
}
@ -877,32 +897,63 @@ lesskey(filename, sysvar)
return (new_lesskey(buf, (int)len, sysvar));
}
#if HAVE_LESSKEYSRC
public int
lesskey_src(filename, sysvar)
char *filename;
int sysvar;
{
static struct lesskey_tables tables;
int r = parse_lesskey(filename, &tables);
if (r != 0)
return (r);
add_fcmd_table(tables.cmdtable.buf.data, tables.cmdtable.buf.end);
add_ecmd_table(tables.edittable.buf.data, tables.edittable.buf.end);
add_var_table(sysvar ? &list_sysvar_tables : &list_var_tables,
tables.vartable.buf.data, tables.vartable.buf.end);
return (0);
}
void
lesskey_parse_error(s)
char *s;
{
PARG parg;
parg.p_string = s;
error("%s", &parg);
}
#endif /* HAVE_LESSKEYSRC */
/*
* Add the standard lesskey file "$HOME/.less"
* Add a lesskey file.
*/
public void
add_hometable(envname, def_filename, sysvar)
public int
add_hometable(call_lesskey, envname, def_filename, sysvar)
int (*call_lesskey)(char *, int);
char *envname;
char *def_filename;
int sysvar;
{
char *filename;
PARG parg;
int r;
if (envname != NULL && (filename = lgetenv(envname)) != NULL)
filename = save(filename);
else if (sysvar)
else if (sysvar) /* def_filename is full path */
filename = save(def_filename);
else
filename = homefile(def_filename);
if (filename == NULL)
return;
if (lesskey(filename, sysvar) < 0)
else /* def_filename is just basename */
{
parg.p_string = filename;
error("Cannot use lesskey file \"%s\"", &parg);
char *xdg = lgetenv("XDG_CONFIG_HOME");
if (!isnullenv(xdg))
filename = dirfile(xdg, def_filename+1, 1);
if (filename == NULL)
filename = homefile(def_filename);
}
if (filename == NULL)
return -1;
r = (*call_lesskey)(filename, sysvar);
free(filename);
return (r);
}
#endif

View File

@ -122,6 +122,7 @@
#define LESSKEYFILE "_less"
#define LESSKEYFILE_SYS "c:\\_sysless"
#define DEF_LESSKEYINFILE "_lesskey"
#define LESSKEYINFILE_SYS "c:\\_syslesskey"
#define LESSHISTFILE "_lesshst"
@ -187,6 +188,9 @@
*/
#define HAVE_DUP 1
/* Define to 1 to support reading lesskey source files (not just binary). */
#define HAVE_LESSKEYSRC 1
/*
* Sizes of various buffers.
*/

View File

@ -80,7 +80,7 @@
* PIPEC is 1 if you wish to have the "|" command
* which allows the user to pipe data into a shell command.
*/
#define PIPEC (!SECURE)
#define PIPEC (!SECURE && HAVE_POPEN)
/*
* LOGFILE is 1 if you wish to allow the -o option (to create log files).
@ -112,6 +112,7 @@
#define LESSKEYFILE ".less"
#define LESSKEYFILE_SYS SYSDIR "/sysless"
#define DEF_LESSKEYINFILE ".lesskey"
#define LESSKEYINFILE_SYS SYSDIR "/syslesskey"
#define LESSHISTFILE ".lesshst"
@ -184,6 +185,9 @@
/* Define to 1 if you have the strstr() function. */
#define HAVE_STRSTR 1
/* Define to 1 to support reading lesskey source files (not just binary). */
#define HAVE_LESSKEYSRC 1
/*
* Sizes of various buffers.
*/

View File

@ -115,6 +115,7 @@
#define LESSKEYFILE "less.ini"
#define LESSKEYFILE_SYS "C:\\sysless.ini"
#define DEF_LESSKEYINFILE "lesskey.ini"
#define LESSKEYINFILE_SYS "C:\\syslesskey.ini"
#define LESSHISTFILE "lesshst.ini"
@ -168,6 +169,9 @@
*/
#define HAVE_DUP 1
/* Define to 1 to support reading lesskey source files (not just binary). */
#define HAVE_LESSKEYSRC 1
/*
* Sizes of various buffers.
*/

View File

@ -114,6 +114,7 @@
#define LESSKEYFILE ".less"
#define LESSKEYFILE_SYS "/.sysless"
#define DEF_LESSKEYINFILE ".lesskey"
#define LESSKEYINFILE_SYS "/.syslesskey"
#define LESSHISTFILE ".lesshst"
@ -175,6 +176,9 @@
*/
#define HAVE_DUP 0
/* Define to 1 to support reading lesskey source files (not just binary). */
#define HAVE_LESSKEYSRC 1
/*
* Sizes of various buffers.
*/

View File

@ -115,6 +115,7 @@
#define LESSKEYFILE "_less"
#define LESSKEYFILE_SYS "c:\\_sysless"
#define DEF_LESSKEYINFILE "_lesskey"
#define LESSKEYINFILE_SYS "c:\\_syslesskey"
#define LESSHISTFILE "_lesshst"
@ -169,6 +170,9 @@
*/
#define HAVE_DUP 1
/* Define to 1 to support reading lesskey source files (not just binary). */
#define HAVE_LESSKEYSRC 1
/*
* Sizes of various buffers.
*/

4
edit.c
View File

@ -26,6 +26,7 @@ extern int force_open;
extern int is_tty;
extern int sigs;
extern int hshift;
extern int want_filesize;
extern IFILE curr_ifile;
extern IFILE old_ifile;
extern struct scrpos initial_scrpos;
@ -487,7 +488,8 @@ edit_ifile(ifile)
cmd_addhist(ml_examine, qfilename, 1);
free(qfilename);
}
if (want_filesize)
scan_eof();
}
free(filename);
return (0);

View File

@ -216,10 +216,11 @@ shell_quote(s)
* Return a pathname that points to a specified file in a specified directory.
* Return NULL if the file does not exist in the directory.
*/
static char *
dirfile(dirname, filename)
public char *
dirfile(dirname, filename, must_exist)
char *dirname;
char *filename;
int must_exist;
{
char *pathname;
int len;
@ -235,17 +236,20 @@ dirfile(dirname, filename)
if (pathname == NULL)
return (NULL);
SNPRINTF3(pathname, len, "%s%s%s", dirname, PATHNAME_SEP, filename);
/*
* Make sure the file exists.
*/
f = open(pathname, OPEN_READ);
if (f < 0)
if (must_exist)
{
free(pathname);
pathname = NULL;
} else
{
close(f);
/*
* Make sure the file exists.
*/
f = open(pathname, OPEN_READ);
if (f < 0)
{
free(pathname);
pathname = NULL;
} else
{
close(f);
}
}
return (pathname);
}
@ -259,25 +263,19 @@ homefile(filename)
{
char *pathname;
/*
* Try $HOME/filename.
*/
pathname = dirfile(lgetenv("HOME"), filename);
/* Try $HOME/filename. */
pathname = dirfile(lgetenv("HOME"), filename, 1);
if (pathname != NULL)
return (pathname);
#if OS2
/*
* Try $INIT/filename.
*/
pathname = dirfile(lgetenv("INIT"), filename);
/* Try $INIT/filename. */
pathname = dirfile(lgetenv("INIT"), filename, 1);
if (pathname != NULL)
return (pathname);
#endif
#if MSDOS_COMPILER || OS2
/*
* Look for the file anywhere on search path.
*/
pathname = (char *) calloc(_MAX_PATH, sizeof(char));
/* Look for the file anywhere on search path. */
pathname = (char *) ecalloc(_MAX_PATH, sizeof(char));
#if MSDOS_COMPILER==DJGPPC
{
char *res = searchpath(filename);
@ -517,6 +515,7 @@ seek_filesize(f)
return ((POSITION) spos);
}
#if HAVE_POPEN
/*
* Read a string from a file.
* Return a pointer to the string in memory.
@ -560,10 +559,6 @@ readfd(fd)
return (buf);
}
#if HAVE_POPEN
/*
* Execute a shell command.
* Return a pointer to a pipe connected to the shell command's standard output.
@ -812,6 +807,7 @@ lrealpath(path)
return (save(path));
}
#if HAVE_POPEN
/*
* Return number of %s escapes in a string.
* Return a large number if there are any other % escapes besides %s.
@ -837,6 +833,7 @@ num_pct_s(lessopen)
}
return (num);
}
#endif
/*
* See if we should open a "replacement file"
@ -953,10 +950,13 @@ open_altfile(filename, pf, pfd)
cmd = readfd(fd);
pclose(fd);
if (*cmd == '\0')
{
/*
* Pipe is empty. This means there is no alt file.
*/
free(cmd);
return (NULL);
}
return (cmd);
#endif /* HAVE_POPEN */
}
@ -1122,4 +1122,3 @@ last_component(name)
}
return (name);
}

12
funcs.h
View File

@ -106,7 +106,8 @@ public int ecmd_decode LESSPARAMS ((char *cmd, char **sp));
public char * lgetenv LESSPARAMS ((char *var));
public int isnullenv LESSPARAMS ((char* s));
public int lesskey LESSPARAMS ((char *filename, int sysvar));
public void add_hometable LESSPARAMS ((char *envname, char *def_filename, int sysvar));
public int lesskey_src LESSPARAMS ((char *filename, int sysvar));
public int add_hometable LESSPARAMS ((int (*call_lesskey)(char *, int), char *envname, char *def_filename, int sysvar));
public int editchar LESSPARAMS ((int c, int flags));
public void init_textlist LESSPARAMS ((struct textlist *tlist, char *str));
public char * forw_textlist LESSPARAMS ((struct textlist *tlist, char *prev));
@ -129,6 +130,7 @@ public void use_logfile LESSPARAMS ((char *filename));
public char * shell_unquote LESSPARAMS ((char *str));
public char * get_meta_escape LESSPARAMS ((VOID_PARAM));
public char * shell_quote LESSPARAMS ((char *s));
public char * dirfile LESSPARAMS ((char *dirname, char *filename, int must_exist));
public char * homefile LESSPARAMS ((char *filename));
public char * fexpand LESSPARAMS ((char *s));
public char * fcomplete LESSPARAMS ((char *s));
@ -213,6 +215,7 @@ public void add_lnum LESSPARAMS ((LINENUM linenum, POSITION pos));
public LINENUM find_linenum LESSPARAMS ((POSITION pos));
public POSITION find_pos LESSPARAMS ((LINENUM linenum));
public LINENUM currline LESSPARAMS ((int where));
public void scan_eof LESSPARAMS ((VOID_PARAM));
public void lsystem LESSPARAMS ((char *cmd, char *donemsg));
public int pipe_mark LESSPARAMS ((int c, char *cmd));
public int pipe_data LESSPARAMS ((char *cmd, POSITION spos, POSITION epos));
@ -235,6 +238,7 @@ public void calc_jump_sline LESSPARAMS ((VOID_PARAM));
public void opt_shift LESSPARAMS ((int type, char *s));
public void calc_shift_count LESSPARAMS ((VOID_PARAM));
public void opt_k LESSPARAMS ((int type, char *s));
public void opt_ks LESSPARAMS ((int type, char *s));
public void opt_t LESSPARAMS ((int type, char *s));
public void opt__T LESSPARAMS ((int type, char *s));
public void opt_p LESSPARAMS ((int type, char *s));
@ -251,6 +255,7 @@ public void opt_mousecap LESSPARAMS ((int type, char *s));
public void opt_wheel_lines LESSPARAMS ((int type, char *s));
public void opt_linenum_width LESSPARAMS ((int type, char *s));
public void opt_status_col_width LESSPARAMS ((int type, char *s));
public void opt_filesize LESSPARAMS ((int type, char *s));
public void opt_ttyin_name LESSPARAMS ((int type, char *s));
public void opt_rstat LESSPARAMS ((int type, char *s));
public int get_swindow LESSPARAMS ((VOID_PARAM));
@ -280,6 +285,7 @@ public void put_line LESSPARAMS ((VOID_PARAM));
public void flush LESSPARAMS ((VOID_PARAM));
public void set_output LESSPARAMS ((int fd));
public int putchr LESSPARAMS ((int c));
public void clear_bot_if_needed LESSPARAMS ((VOID_PARAM));
public void putstr LESSPARAMS ((constant char *s));
public int less_printf LESSPARAMS ((char *fmt, PARG *parg));
public void get_return LESSPARAMS ((VOID_PARAM));
@ -342,3 +348,7 @@ public void close_getchr LESSPARAMS ((VOID_PARAM));
public int default_wheel_lines LESSPARAMS ((VOID_PARAM));
public void rstat LESSPARAMS ((char st));
public int getchr LESSPARAMS ((VOID_PARAM));
public void xbuf_init LESSPARAMS ((struct xbuffer *xbuf));
public void xbuf_deinit LESSPARAMS ((struct xbuffer *xbuf));
public void xbuf_reset LESSPARAMS ((struct xbuffer *xbuf));
public void xbuf_add LESSPARAMS ((struct xbuffer *xbuf, char ch));

4
help.c
View File

@ -1,4 +1,4 @@
/* This file was generated by mkhelp.pl from less.hlp at 14:59 on 2021/4/28 */
/* This file was generated by mkhelp.pl from less.hlp at 17:45 on 2021/6/3 */
#include "less.h"
constant char helpdata[] = {
'\n',
@ -208,6 +208,8 @@ constant char helpdata[] = {
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','D','o','n','\'','t',' ','d','i','s','p','l','a','y',' ','t','i','l','d','e','s',' ','a','f','t','e','r',' ','e','n','d',' ','o','f',' ','f','i','l','e','.','\n',
' ',' ','-','#',' ','[','_','\b','N',']',' ',' ','.','.','.','.',' ',' ','-','-','s','h','i','f','t','=','[','_','\b','N',']','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','S','e','t',' ','h','o','r','i','z','o','n','t','a','l',' ','s','c','r','o','l','l',' ','a','m','o','u','n','t',' ','(','0',' ','=',' ','o','n','e',' ','h','a','l','f',' ','s','c','r','e','e','n',' ','w','i','d','t','h',')','.','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','f','i','l','e','-','s','i','z','e','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','A','u','t','o','m','a','t','i','c','a','l','l','y',' ','d','e','t','e','r','m','i','n','e',' ','t','h','e',' ','s','i','z','e',' ','o','f',' ','t','h','e',' ','i','n','p','u','t',' ','f','i','l','e','.','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','f','o','l','l','o','w','-','n','a','m','e','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','T','h','e',' ','F',' ','c','o','m','m','a','n','d',' ','c','h','a','n','g','e','s',' ','f','i','l','e','s',' ','i','f',' ','t','h','e',' ','i','n','p','u','t',' ','f','i','l','e',' ','i','s',' ','r','e','n','a','m','e','d','.','\n',
' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','-','-','i','n','c','s','e','a','r','c','h','\n',

1
less.h
View File

@ -571,6 +571,7 @@ struct loption;
struct hilite_tree;
struct ansi_state;
#include "pattern.h"
#include "xbuf.h"
#include "funcs.h"
/* Functions not included in funcs.h */

View File

@ -205,6 +205,8 @@
Don't display tildes after end of file.
-# [_N] .... --shift=[_N]
Set horizontal scroll amount (0 = one half screen width).
--file-size
Automatically determine the size of the input file.
--follow-name
The F command changes files if the input file is renamed.
--incsearch

503
less.man
View File

@ -723,10 +723,21 @@ LESS(1) General Commands Manual LESS(1)
-kfilename or --lesskey-file=filename
Causes less to open and interpret the named file as a lesskey(1)
file. Multiple -k options 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 lesskey file.
binary file. Multiple -k options 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 lesskey file.
--lesskey-src=filename
Causes less to open and interpret the named file as a lesskey(1)
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 lesskey program needed
to be run to convert a lesskey source file to a lesskey binary
file for less to use. Newer versions of less read the lesskey
source file directly and ignore the binary file if the source
file exists.
-K or --quit-on-intr
Causes less to exit immediately (with status 2) when an inter-
@ -986,6 +997,11 @@ LESS(1) General Commands Manual LESS(1)
calculated if the terminal window is resized, so that the actual
scroll remains at the specified fraction of the screen width.
--file-size
If --file-size is specified, less will determine the size of the
file immediately after opening the file. Normally this is not
done, because it can be slow if the input file is large.
--follow-name
Normally, if the input file is renamed while an F command is ex-
ecuting, less will continue to display the contents of the orig-
@ -1164,70 +1180,75 @@ LESS(1) General Commands Manual LESS(1)
^G Delete the entire command line and return to the main prompt.
KEY BINDINGS
You may define your own less commands by using the program lesskey(1)
to create a lesskey file. This file specifies a set of command keys
and an action associated with each key. You may also use lesskey to
change the line-editing keys (see LINE EDITING), and to set environment
variables. If the environment variable LESSKEY is set, less uses that
as the name of the lesskey file. Otherwise, less looks in a standard
place for the lesskey file: On Unix systems, less looks for a lesskey
file called "$HOME/.less". On MS-DOS and Windows systems, less looks
for a lesskey file called "$HOME/_less", and if it is not found there,
then looks for a lesskey file called "_less" in any directory specified
in the PATH environment variable. On OS/2 systems, less looks for a
lesskey file called "$HOME/less.ini", and if it is not found, then
looks for a lesskey file called "less.ini" in any directory specified
in the INIT environment variable, and if it not found there, then looks
for a lesskey file called "less.ini" in any directory specified in the
PATH environment variable. See the lesskey manual page for more de-
tails.
You may define your own less commands 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 to set environment variables. If the environment
variable LESSKEYIN is set, less uses that as the name of the lesskey
source file. Otherwise, less looks in a standard place for the lesskey
source file: On Unix systems, less looks for a lesskey file called
"$XDG_CONFIG_HOME/lesskey" or "$HOME/.lesskey". On MS-DOS and Windows
systems, less 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 directory specified in the PATH environment variable. On OS/2
systems, less looks 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. See the
lesskey manual page for more details.
A system-wide lesskey 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 LESSKEY_SYSTEM is set,
less uses that as the name of the system-wide lesskey file. Otherwise,
less looks in a standard place for the system-wide lesskey file: On
Unix systems, the system-wide lesskey file is /usr/local/etc/sysless.
(However, if less was built with a different 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:\_sys-
less. On OS/2 systems, the system-wide lesskey file is c:\sysless.ini.
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, less uses that as the name of the system-wide
lesskey file. Otherwise, less looks 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 less was 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.ini.
Previous versions of less (before v582) used lesskey files with a bina-
ry format, produced by the lesskey program. It is no longer necessary
to use the lesskey program.
INPUT PREPROCESSOR
You may define an "input preprocessor" for less. Before less opens a
You may define an "input preprocessor" for less. Before less opens a
file, it first gives your 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
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, less will 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, less will 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, less uses 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, less uses 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 less closes 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 less view them directly:
lessopen.sh:
@ -1247,27 +1268,27 @@ LESS(1) General Commands Manual LESS(1)
#! /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 less, 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 less, 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 less uses 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 less uses 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:
@ -1284,29 +1305,29 @@ LESS(1) General Commands Manual LESS(1)
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 becomes meaningful. If the exit status is
zero, the output is considered to be replacement text, even if it is
empty. If the exit status is nonzero, any output is ignored and the
original file is used. For compatibility with previous versions of
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 becomes meaningful. If the exit status is
zero, the output is considered to be replacement text, even if it is
empty. If the exit status is nonzero, any output is ignored and the
original file is used. For compatibility with previous versions of
less, 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 less, the input preproces-
For compatibility with previous versions of less, the input preproces-
sor or pipe is not used if less is 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 (-), 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 (|-) or two vertical bars
and a dash (||-), 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.
@ -1317,25 +1338,25 @@ LESS(1) General Commands Manual LESS(1)
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.
A "character set" is simply a description of which characters are to be
considered normal, control, and binary. The LESSCHARSET environment
variable may be used to select a character set. Possible values for
considered normal, control, and binary. 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.
@ -1347,8 +1368,8 @@ LESS(1) General Commands Manual LESS(1)
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.
@ -1356,29 +1377,29 @@ LESS(1) General Commands Manual LESS(1)
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
1251).
In rare cases, it may be desired to tailor less to 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 less to 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
@ -1392,65 +1413,65 @@ LESS(1) General Commands Manual LESS(1)
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 setlocale in-
terface, less will use setlocale to determine the character set. set-
locale is controlled by setting the LANG or LC_CTYPE environment vari-
terface, less will use setlocale to determine the character set. set-
locale is controlled by setting the LANG or LC_CTYPE environment vari-
ables.
Finally, if the setlocale interface is also not available, the default
Finally, if the setlocale interface is also not available, the default
character set is latin1.
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.
PROMPTS
The -P option allows you to tailor the prompt to your preference. The
string given to the -P option replaces the specified prompt string.
The -P option allows you to tailor the prompt to your preference. The
string given to the -P option 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
A percent sign followed by a single character is expanded according to
what the following character is:
%bX Replaced by the byte offset into the current input file. The b
%bX Replaced by the byte offset into the current input file. The b
is followed by a single character (shown as X 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 -j
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 -j
option.
%B Replaced by the size of the current input file.
@ -1458,50 +1479,50 @@ LESS(1) General Commands Manual LESS(1)
%c Replaced by the column number of the text appearing in the first
column of the screen.
%dX Replaced by the page number of a line in the input file. The
%dX Replaced by the page number of a line in the input file. The
line to be used is determined by the X, 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.
%lX Replaced by the line number of a line in the input file. The
%lX Replaced by the line number of a line in the input file. The
line to be used is determined by the X, 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.
%pX Replaced by the percent into the current input file, based on
byte offsets. The line used is determined by the X as with the
%pX Replaced by the percent into the current input file, based on
byte offsets. The line used is determined by the X as with the
%b option.
%PX Replaced by the percent into the current input file, based on
line numbers. The line used is determined by the X as with the
%PX Replaced by the percent into the current input file, based on
line numbers. The line used is determined by the X as with the
%b option.
%s Same as %B.
%t Causes any trailing spaces to be removed. Usually used at the
%t Causes any trailing spaces to be removed. Usually used at the
end of the string, but may appear anywhere.
%T Normally expands to the word "file". However if viewing files
via a tags list using the -t option, it expands to the word
%T Normally expands to the word "file". However if viewing files
via a tags list using the -t option, it expands to the word
"tag".
%x Replaced by the name of the next input file in the list.
@ -1509,15 +1530,15 @@ LESS(1) General Commands Manual LESS(1)
If any item is unknown (for example, the file size if input is a pipe),
a question mark is printed instead.
The format of the prompt string can be changed depending on certain
conditions. A question mark followed by a single character acts like
an "IF": depending on the following character, a condition is evaluat-
ed. If the condition is true, any characters following the question
mark and condition character, up to a period, are included in the
prompt. If the condition is false, such characters are not included.
A colon appearing between the question mark and the period can be used
The format of the prompt string can be changed depending on certain
conditions. A question mark followed by a single character acts like
an "IF": depending on the following character, a condition is evaluat-
ed. If the condition is true, any characters following the question
mark and condition character, up to a period, are included in the
prompt. If the condition is false, such characters are not included.
A colon appearing between the question mark and the period can be used
to establish an "ELSE": any characters between the colon and the period
are included in the string if and only if the IF condition is false.
are included in the string if and only if the IF condition is false.
Condition characters (which follow a question mark) may be:
?a True if any characters have been included in the prompt so far.
@ -1532,7 +1553,7 @@ LESS(1) General Commands Manual LESS(1)
?e True if at end-of-file.
?f True if there is an input filename (that is, if input is not a
?f True if there is an input filename (that is, if input is not a
pipe).
?lX True if the line number of the specified line is known.
@ -1543,45 +1564,45 @@ LESS(1) General Commands Manual LESS(1)
?n True if this is the first prompt in a new input file.
?pX True if the percent into the current input file, based on byte
?pX True if the percent into the current input file, based on byte
offsets, of the specified line is known.
?PX True if the percent into the current input file, based on line
?PX True if the percent into the current input file, based on line
numbers, of the specified line is known.
?s Same as "?B".
?x True if there is a next input file (that is, if the current in-
?x True if there is a next input file (that is, if the current in-
put file is not the last one).
Any characters other than the special ones (question mark, colon, peri-
od, percent, and backslash) become literally part of the prompt. Any
of the special characters may be included in the prompt literally by
od, percent, and backslash) become literally part of the prompt. Any
of the special characters may be included in the prompt literally by
preceding it with a backslash.
Some examples:
?f%f:Standard input.
This prompt prints the filename, if known; otherwise the string "Stan-
This prompt prints the filename, if known; otherwise the string "Stan-
dard input".
?f%f .?ltLine %lt:?pt%pt\%:?btByte %bt:-...
This prompt would print the filename, if known. The filename is fol-
lowed by the line number, if known, otherwise the percent if known,
This prompt would print the filename, if known. The filename is fol-
lowed by the line number, if known, otherwise the percent if known,
otherwise the byte offset if known. Otherwise, a dash is printed. No-
tice how each question mark has a matching period, and how the % after
tice how each question mark has a matching period, and how the % after
the %pt is included literally by escaping it with a backslash.
?n?f%f .?m(%T %i of %m) ..?e(END) ?x- Next\: %x..%t";
This prints the filename if this is the first prompt in a file, fol-
lowed by the "file N of N" message if there is more than one input
file. Then, if we are at end-of-file, the string "(END)" is printed
followed by the name of the next file, if there is one. Finally, any
This prints the filename if this is the first prompt in a file, fol-
lowed by the "file N of N" message if there is more than one input
file. Then, if we are at end-of-file, the string "(END)" is printed
followed by the name of the next file, if there is one. Finally, any
trailing spaces are truncated. This is the default prompt. For refer-
ence, here are the defaults for the other two prompts (-m and -M re-
ence, here are the defaults for the other two prompts (-m and -M re-
spectively). Each is broken into two lines here for readability only.
?n?f%f .?m(%T %i of %m) ..?e(END) ?x- Next\: %x.:
@ -1595,22 +1616,22 @@ LESS(1) General Commands Manual LESS(1)
?f%f .?m(%T %i of %m) .?ltlines %lt-%lb?L/%L. .
byte %bB?s/%s. ?e(END) :?pB%pB\%..%t
The prompt expansion features are also used for another purpose: if an
environment variable LESSEDIT is defined, it is used as the command to
be executed when the v command is invoked. The LESSEDIT string is ex-
panded in the same way as the prompt strings. The default value for
The prompt expansion features are also used for another purpose: if an
environment variable LESSEDIT is defined, it is used as the command to
be executed when the v command is invoked. The LESSEDIT string is ex-
panded in the same way as the prompt strings. The default value for
LESSEDIT is:
%E ?lm+%lm. %g
Note that this expands to the editor name, followed by a + and the line
number, followed by the shell-escaped file name. If your editor does
not accept the "+linenumber" syntax, or has other differences in invo-
cation syntax, the LESSEDIT variable can be changed to modify this de-
number, followed by the shell-escaped file name. If your editor does
not accept the "+linenumber" syntax, or has other differences in invo-
cation syntax, the LESSEDIT variable can be changed to modify this de-
fault.
SECURITY
When the environment variable LESSSECURE is set to 1, less runs in a
When the environment variable LESSSECURE is set to 1, less runs in a
"secure" mode. This means these features are disabled:
! the shell command
@ -1635,52 +1656,52 @@ LESS(1) General Commands Manual LESS(1)
COMPATIBILITY WITH MORE
If the environment variable LESS_IS_MORE is set to 1, or if the program
is invoked via a file link named "more", less behaves (mostly) in con-
formance with the POSIX "more" command specification. In this mode,
is invoked via a file link named "more", less behaves (mostly) in con-
formance with the POSIX "more" command specification. In this mode,
less behaves differently in these ways:
The -e option works differently. If the -e option is not set, less be-
haves as if the -e option were set. If the -e option is set, less be-
haves as if the -e option were set. If the -e option is set, less be-
haves as if the -E option were set.
The -m option works differently. If the -m option is not set, the
medium prompt is used, and it is prefixed with the string "--More--".
The -m option works differently. If the -m option is not set, the
medium prompt is used, and it is prefixed with the string "--More--".
If the -m option is set, the short prompt is used.
The -n option acts like the -z option. The normal behavior of the -n
The -n option acts like the -z option. The normal behavior of the -n
option is unavailable in this mode.
The parameter to the -p option is taken to be a less command rather
The parameter to the -p option is taken to be a less command rather
than a search pattern.
The LESS environment variable is ignored, and the MORE environment
The LESS environment variable is ignored, and the MORE environment
variable is used in its place.
ENVIRONMENT VARIABLES
Environment variables may be specified either in the system environment
as usual, or in a lesskey(1) file. If environment variables are de-
as usual, or in a lesskey(1) file. If environment variables are de-
fined in more than one place, variables defined in a local lesskey file
take precedence over variables defined in the system environment, which
take precedence over variables defined in the system-wide lesskey file.
COLUMNS
Sets the number of columns on the screen. Takes precedence over
the number of columns specified by the TERM variable. (But if
the number of columns 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
WIOCGETD, the window system's idea of the screen size takes
precedence over the LINES and COLUMNS environment variables.)
EDITOR The name of the editor (used for the v command).
HOME Name of the user's home directory (used to find a lesskey file
HOME Name of the user's home directory (used to find a lesskey file
on Unix and OS/2 systems).
HOMEDRIVE, HOMEPATH
Concatenation of the HOMEDRIVE and HOMEPATH environment vari-
Concatenation of the HOMEDRIVE and HOMEPATH environment vari-
ables is the name of the user's home directory if the HOME vari-
able is not set (only in the Windows version).
INIT Name of the user's init directory (used to find a lesskey file
INIT Name of the user's init directory (used to find a lesskey file
on OS/2 systems).
LANG Language for determining the character set.
@ -1691,12 +1712,12 @@ LESS(1) General Commands Manual LESS(1)
LESS Options which are passed to less automatically.
LESSANSIENDCHARS
Characters which may end an ANSI color escape sequence (default
Characters which may end an ANSI color escape sequence (default
"m").
LESSANSIMIDCHARS
Characters which may appear between the ESC character and the
end character in an ANSI color escape sequence (default
Characters which may appear between the ESC character and the
end character in an ANSI color escape sequence (default
"0123456789:;[?!"'#%()*+ ".
LESSBINFMT
@ -1713,44 +1734,52 @@ LESS(1) General Commands Manual LESS(1)
LESSECHO
Name of the lessecho program (default "lessecho"). The lessecho
program is needed to expand metacharacters, such as * and ?, in
program is needed to expand metacharacters, such as * and ?, in
filenames on Unix systems.
LESSEDIT
Editor prototype string (used for the v command). See discus-
Editor prototype string (used for the v command). See discus-
sion under PROMPTS.
LESSGLOBALTAGS
Name of the command used by the -t option to find global tags.
Normally should be set to "global" if your system has the glob-
Name of the command used by the -t option to find global tags.
Normally should be set to "global" if your system has the glob-
al(1) command. If not set, global tags are not used.
LESSHISTFILE
Name of the history file used to remember search commands and
shell commands between invocations of less. If set to "-" or
"/dev/null", a history file is not used. The default is
"$HOME/.lesshst" on Unix systems, "$HOME/_lesshst" on DOS and
Windows systems, or "$HOME/lesshst.ini" or "$INIT/lesshst.ini"
on OS/2 systems.
Name of the history file used to remember search commands and
shell commands between invocations of less. If set to "-" or
"/dev/null", a history file is not used. The default is
"$XDG_DATA_HOME/lesshst" or "$HOME/.lesshst" on Unix systems,
"$HOME/_lesshst" on DOS and Windows systems, or
"$HOME/lesshst.ini" or "$INIT/lesshst.ini" on OS/2 systems.
LESSHISTSIZE
The maximum number of commands to save in the history file. The
default is 100.
LESSKEYIN
Name of the default lesskey source file.
LESSKEY
Name of the default lesskey(1) file.
Name of the default lesskey binary file. (Not used if
"$LESSKEYIN" exists.)
LESSKEYIN_SYSTEM
Name of the default system-wide lesskey source file.
LESSKEY_SYSTEM
Name of the default system-wide lesskey(1) file.
Name of the default system-wide lesskey binary file. (Not used
if "$LESSKEYIN_SYSTEM" exists.)
LESSMETACHARS
List of characters which are considered "metacharacters" by the
List of characters which are considered "metacharacters" by the
shell.
LESSMETAESCAPE
Prefix which less will add before each metacharacter in a com-
mand sent to the shell. If LESSMETAESCAPE is an empty string,
commands containing metacharacters will not be passed to the
Prefix which less will add before each metacharacter in a com-
mand sent to the shell. If LESSMETAESCAPE is an empty string,
commands containing metacharacters will not be passed to the
shell.
LESSOPEN
@ -1760,7 +1789,7 @@ LESS(1) General Commands Manual LESS(1)
Runs less in "secure" mode. See discussion under SECURITY.
LESSSEPARATOR
String to be appended to a directory name in filename comple-
String to be appended to a directory name in filename comple-
tion.
LESSUTFBINFMT
@ -1769,19 +1798,19 @@ LESS(1) General Commands Manual LESS(1)
LESS_IS_MORE
Emulate the more(1) command.
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 less automatically when running in
MORE Options which are passed to less automatically when running in
more compatible mode.
PATH User's search path (used to find a lesskey file on MS-DOS and
PATH User's search path (used to find a lesskey file on MS-DOS and
OS/2 systems).
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 less is being run.
@ -1794,27 +1823,27 @@ LESS(1) General Commands Manual LESS(1)
COPYRIGHT
Copyright (C) 1984-2021 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.
AUTHOR
Mark Nudelman
Report bugs at https://github.com/gwsw/less/issues.
For more information, see the less homepage at
https://greenwoodsoftware.com/less.
https://greenwoodsoftware.com/less
Version 581.2: 28 Apr 2021 LESS(1)
Version 590: 03 Jun 2021 LESS(1)

102
less.nro
View File

@ -1,5 +1,5 @@
'\" t
.TH LESS 1 "Version 581.2: 28 Apr 2021"
.TH LESS 1 "Version 590: 03 Jun 2021"
.SH NAME
less \- opposite of more
.SH SYNOPSIS
@ -759,13 +759,38 @@ Causes
.I less
to open and interpret the named file as a
.IR lesskey (1)
file.
binary file.
Multiple \-k options 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
.I lesskey
file.
.IP "\-\-lesskey-src=\fIfilename\fP"
Causes
.I less
to open and interpret the named file as a
.IR lesskey (1)
source file.
If the LESSKEYIN or LESSKEYIN_SYSTEM environment variable is set, or
if a lesskey source file is found in a standard place (see KEY BINDINGS),
it is also used as a
.I "lesskey source"
file.
Prior to version 582, the
.I lesskey
program needed to be run to convert a
.I "lesskey source"
file to a
.I "lesskey binary"
file for
.I less
to use.
Newer versions of
.I less
read the
.I "lesskey source"
file directly and ignore the binary file if the source file exists.
.IP "\-K or \-\-quit-on-intr"
Causes
.I less
@ -1054,6 +1079,12 @@ If the number is specified as a fraction, the actual number of
scroll positions is recalculated if the terminal window is resized,
so that the actual scroll remains at the specified fraction
of the screen width.
.IP "\-\-file-size"
If \-\-file-size is specified,
.I less
will determine the size of the file
immediately after opening the file.
Normally this is not done, because it can be slow if the input file is large.
.IP "\-\-follow-name"
Normally, if the input file is renamed while an F command is executing,
.I less
@ -1222,57 +1253,61 @@ Delete the entire command line and return to the main prompt.
.SH "KEY BINDINGS"
You may define your own
.I less
commands by using the program
.IR lesskey (1)
to create a lesskey file.
commands by creating a lesskey source file.
This file specifies a set of command keys and an action
associated with each key.
You may also use
.I lesskey
to change the line-editing keys (see LINE EDITING),
You may also change the line-editing keys (see LINE EDITING),
and to set environment variables.
If the environment variable LESSKEY is set,
If the environment variable LESSKEYIN is set,
.I less
uses that as the name of the lesskey file.
uses that as the name of the lesskey source file.
Otherwise,
.I less
looks in a standard place for the lesskey file:
looks in a standard place for the lesskey source file:
On Unix systems,
.I less
looks for a lesskey file called "$HOME/.less".
looks for a lesskey file called "$XDG_CONFIG_HOME/lesskey" or "$HOME/.lesskey".
On MS-DOS and Windows systems,
.I less
looks for a lesskey file called "$HOME/_less", and if it is not found there,
then looks for a lesskey file called "_less" in any directory specified
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 directory specified
in the PATH environment variable.
On OS/2 systems,
.I less
looks for a lesskey file called "$HOME/less.ini", and if it is not found,
then looks for a lesskey file called "less.ini" in any directory specified
looks 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 "less.ini" in any directory specified
then looks for a lesskey file called "lesskey.ini" in any directory specified
in the PATH environment variable.
See the
.I lesskey
manual page for more details.
.P
A system-wide lesskey file may also be set up to provide key bindings.
.PP
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 LESSKEY_SYSTEM is set,
If the environment variable LESSKEYIN_SYSTEM is set,
.I less
uses that as the name of the system-wide lesskey file.
Otherwise,
.I less
looks in a standard place for the system-wide lesskey file:
On Unix systems, the system-wide lesskey file is /usr/local/etc/sysless.
On Unix systems, the system-wide lesskey file is /usr/local/etc/syslesskey.
(However, if
.I less
was built with a different 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:\e_sysless.
On OS/2 systems, the system-wide lesskey file is c:\esysless.ini.
On MS-DOS and Windows systems, the system-wide lesskey file is c:\e_syslesskey.
On OS/2 systems, the system-wide lesskey file is c:\esyslesskey.ini.
.PP
Previous versions of
.I less
(before v582) used lesskey files with a binary format, produced by the
.I lesskey
program. It is no longer necessary to use the
.I lesskey
program.
.
.SH "INPUT PREPROCESSOR"
You may define an "input preprocessor" for
@ -1890,20 +1925,29 @@ Name of the history file used to remember search commands and
shell commands between invocations of
.IR less .
If set to "\-" or "/dev/null", a history file is not used.
The default is "$HOME/.lesshst" on Unix systems, "$HOME/_lesshst" on
DOS and Windows systems, or "$HOME/lesshst.ini" or "$INIT/lesshst.ini"
The default is "$XDG_DATA_HOME/lesshst" or "$HOME/.lesshst" on Unix systems,
"$HOME/_lesshst" on DOS and Windows systems,
or "$HOME/lesshst.ini" or "$INIT/lesshst.ini"
on OS/2 systems.
.IP LESSHISTSIZE
The maximum number of commands to save in the history file.
The default is 100.
.IP LESSKEYIN
Name of the default
.I "lesskey source"
file.
.IP LESSKEY
Name of the default
.IR lesskey (1)
.I "lesskey binary"
file. (Not used if "$LESSKEYIN" exists.)
.IP LESSKEYIN_SYSTEM
Name of the default system-wide
.I "lesskey source"
file.
.IP LESSKEY_SYSTEM
Name of the default system-wide
.IR lesskey (1)
file.
.I "lesskey binary"
file. (Not used if "$LESSKEYIN_SYSTEM" exists.)
.IP LESSMETACHARS
List of characters which are considered "metacharacters" by the shell.
.IP LESSMETAESCAPE
@ -1981,4 +2025,4 @@ Report bugs at https://github.com/gwsw/less/issues.
.br
For more information, see the less homepage at
.br
https://greenwoodsoftware.com/less.
https://greenwoodsoftware.com/less

View File

@ -51,4 +51,4 @@ LESSECHO(1) General Commands Manual LESSECHO(1)
Version 581.2: 28 Apr 2021 LESSECHO(1)
Version 590: 03 Jun 2021 LESSECHO(1)

View File

@ -1,4 +1,4 @@
.TH LESSECHO 1 "Version 581.2: 28 Apr 2021"
.TH LESSECHO 1 "Version 590: 03 Jun 2021"
.SH NAME
lessecho \- expand metacharacters
.SH SYNOPSIS

607
lesskey.c
View File

@ -80,121 +80,12 @@
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*/
#include "less.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "lesskey.h"
#include "cmd.h"
struct cmdname
{
char *cn_name;
int cn_action;
};
struct cmdname cmdnames[] =
{
{ "back-bracket", A_B_BRACKET },
{ "back-line", A_B_LINE },
{ "back-line-force", A_BF_LINE },
{ "back-screen", A_B_SCREEN },
{ "back-scroll", A_B_SCROLL },
{ "back-search", A_B_SEARCH },
{ "back-window", A_B_WINDOW },
{ "clear-mark", A_CLRMARK },
{ "debug", A_DEBUG },
{ "digit", A_DIGIT },
{ "display-flag", A_DISP_OPTION },
{ "display-option", A_DISP_OPTION },
{ "end", A_GOEND },
{ "end-scroll", A_RRSHIFT },
{ "examine", A_EXAMINE },
{ "filter", A_FILTER },
{ "first-cmd", A_FIRSTCMD },
{ "firstcmd", A_FIRSTCMD },
{ "flush-repaint", A_FREPAINT },
{ "forw-bracket", A_F_BRACKET },
{ "forw-forever", A_F_FOREVER },
{ "forw-until-hilite", A_F_UNTIL_HILITE },
{ "forw-line", A_F_LINE },
{ "forw-line-force", A_FF_LINE },
{ "forw-screen", A_F_SCREEN },
{ "forw-screen-force", A_FF_SCREEN },
{ "forw-scroll", A_F_SCROLL },
{ "forw-search", A_F_SEARCH },
{ "forw-window", A_F_WINDOW },
{ "goto-end", A_GOEND },
{ "goto-end-buffered", A_GOEND_BUF },
{ "goto-line", A_GOLINE },
{ "goto-mark", A_GOMARK },
{ "help", A_HELP },
{ "index-file", A_INDEX_FILE },
{ "invalid", A_UINVALID },
{ "left-scroll", A_LSHIFT },
{ "next-file", A_NEXT_FILE },
{ "next-tag", A_NEXT_TAG },
{ "noaction", A_NOACTION },
{ "no-scroll", A_LLSHIFT },
{ "percent", A_PERCENT },
{ "pipe", A_PIPE },
{ "prev-file", A_PREV_FILE },
{ "prev-tag", A_PREV_TAG },
{ "quit", A_QUIT },
{ "remove-file", A_REMOVE_FILE },
{ "repaint", A_REPAINT },
{ "repaint-flush", A_FREPAINT },
{ "repeat-search", A_AGAIN_SEARCH },
{ "repeat-search-all", A_T_AGAIN_SEARCH },
{ "reverse-search", A_REVERSE_SEARCH },
{ "reverse-search-all", A_T_REVERSE_SEARCH },
{ "right-scroll", A_RSHIFT },
{ "set-mark", A_SETMARK },
{ "set-mark-bottom", A_SETMARKBOT },
{ "shell", A_SHELL },
{ "status", A_STAT },
{ "toggle-flag", A_OPT_TOGGLE },
{ "toggle-option", A_OPT_TOGGLE },
{ "undo-hilite", A_UNDO_SEARCH },
{ "clear-search", A_CLR_SEARCH },
{ "version", A_VERSION },
{ "visual", A_VISUAL },
{ NULL, 0 }
};
struct cmdname editnames[] =
{
{ "back-complete", EC_B_COMPLETE },
{ "backspace", EC_BACKSPACE },
{ "delete", EC_DELETE },
{ "down", EC_DOWN },
{ "end", EC_END },
{ "expand", EC_EXPAND },
{ "forw-complete", EC_F_COMPLETE },
{ "home", EC_HOME },
{ "insert", EC_INSERT },
{ "invalid", EC_UINVALID },
{ "kill-line", EC_LINEKILL },
{ "abort", EC_ABORT },
{ "left", EC_LEFT },
{ "literal", EC_LITERAL },
{ "right", EC_RIGHT },
{ "up", EC_UP },
{ "word-backspace", EC_W_BACKSPACE },
{ "word-delete", EC_W_DELETE },
{ "word-left", EC_W_LEFT },
{ "word-right", EC_W_RIGHT },
{ NULL, 0 }
};
struct table
{
struct cmdname *names;
char *pbuffer;
char buffer[MAX_USERCMD];
};
struct table cmdtable;
struct table edittable;
struct table vartable;
struct table *currtable = &cmdtable;
#include "defines.h"
char fileheader[] = {
C0_LESSKEY_MAGIC,
@ -215,26 +106,44 @@ char endsection[1] = { END_SECTION };
char *infile = NULL;
char *outfile = NULL ;
int linenum;
int errors;
extern char version[];
void
usage(VOID_PARAM)
static void
usage(void)
{
fprintf(stderr, "usage: lesskey [-o output] [input]\n");
exit(1);
}
char *
void
lesskey_parse_error(s)
char *s;
{
fprintf(stderr, "%s\n", s);
}
void *
ecalloc(count, size)
int count;
unsigned int size;
{
void *p;
p = calloc(count, size);
if (p != NULL)
return (p);
fprintf(stderr, "lesskey: cannot allocate %d bytes of memory\n", count*size);
exit(1);
}
static char *
mkpathname(dirname, filename)
char *dirname;
char *filename;
{
char *pathname;
pathname = calloc(strlen(dirname) + strlen(filename) + 2, sizeof(char));
pathname = ecalloc(strlen(dirname) + strlen(filename) + 2, sizeof(char));
strcpy(pathname, dirname);
strcat(pathname, PATHNAME_SEP);
strcat(pathname, filename);
@ -268,7 +177,7 @@ homefile(filename)
/*
* Parse command line arguments.
*/
void
static void
parse_args(argc, argv)
int argc;
char **argv;
@ -336,247 +245,12 @@ parse_args(argc, argv)
*/
if (argc > 0)
infile = *argv;
else
infile = homefile(DEF_LESSKEYINFILE);
}
/*
* Initialize data structures.
*/
void
init_tables(VOID_PARAM)
{
cmdtable.names = cmdnames;
cmdtable.pbuffer = cmdtable.buffer;
edittable.names = editnames;
edittable.pbuffer = edittable.buffer;
vartable.names = NULL;
vartable.pbuffer = vartable.buffer;
}
/*
* Parse one character of a string.
*/
char *
tstr(pp, xlate)
char **pp;
int xlate;
{
char *p;
char ch;
int i;
static char buf[10];
static char tstr_control_k[] =
{ SK_SPECIAL_KEY, SK_CONTROL_K, 6, 1, 1, 1, '\0' };
p = *pp;
switch (*p)
{
case '\\':
++p;
switch (*p)
{
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
/*
* Parse an octal number.
*/
ch = 0;
i = 0;
do
ch = 8*ch + (*p - '0');
while (*++p >= '0' && *p <= '7' && ++i < 3);
*pp = p;
if (xlate && ch == CONTROL('K'))
return tstr_control_k;
buf[0] = ch;
buf[1] = '\0';
return (buf);
case 'b':
*pp = p+1;
return ("\b");
case 'e':
*pp = p+1;
buf[0] = ESC;
buf[1] = '\0';
return (buf);
case 'n':
*pp = p+1;
return ("\n");
case 'r':
*pp = p+1;
return ("\r");
case 't':
*pp = p+1;
return ("\t");
case 'k':
if (xlate)
{
switch (*++p)
{
case 'u': ch = SK_UP_ARROW; break;
case 'd': ch = SK_DOWN_ARROW; break;
case 'r': ch = SK_RIGHT_ARROW; break;
case 'l': ch = SK_LEFT_ARROW; break;
case 'U': ch = SK_PAGE_UP; break;
case 'D': ch = SK_PAGE_DOWN; break;
case 'h': ch = SK_HOME; break;
case 'e': ch = SK_END; break;
case 'x': ch = SK_DELETE; break;
default:
error("illegal char after \\k", NULL_PARG);
*pp = p+1;
return ("");
}
*pp = p+1;
buf[0] = SK_SPECIAL_KEY;
buf[1] = ch;
buf[2] = 6;
buf[3] = 1;
buf[4] = 1;
buf[5] = 1;
buf[6] = '\0';
return (buf);
}
/* FALLTHRU */
default:
/*
* Backslash followed by any other char
* just means that char.
*/
*pp = p+1;
buf[0] = *p;
buf[1] = '\0';
if (xlate && buf[0] == CONTROL('K'))
return tstr_control_k;
return (buf);
}
case '^':
/*
* Caret means CONTROL.
*/
*pp = p+2;
buf[0] = CONTROL(p[1]);
buf[1] = '\0';
if (xlate && buf[0] == CONTROL('K'))
return tstr_control_k;
return (buf);
}
*pp = p+1;
buf[0] = *p;
buf[1] = '\0';
if (xlate && buf[0] == CONTROL('K'))
return tstr_control_k;
return (buf);
}
/*
* Skip leading spaces in a string.
*/
public char *
skipsp(s)
char *s;
{
while (*s == ' ' || *s == '\t')
s++;
return (s);
}
/*
* Skip non-space characters in a string.
*/
public char *
skipnsp(s)
char *s;
{
while (*s != '\0' && *s != ' ' && *s != '\t')
s++;
return (s);
}
/*
* Clean up an input line:
* strip off the trailing newline & any trailing # comment.
*/
char *
clean_line(s)
char *s;
{
int i;
s = skipsp(s);
for (i = 0; s[i] != '\n' && s[i] != '\r' && s[i] != '\0'; i++)
if (s[i] == '#' && (i == 0 || s[i-1] != '\\'))
break;
s[i] = '\0';
return (s);
}
/*
* Add a byte to the output command table.
*/
void
add_cmd_char(c)
int c;
{
if (currtable->pbuffer >= currtable->buffer + MAX_USERCMD)
{
error("too many commands", NULL_PARG);
exit(1);
}
*(currtable->pbuffer)++ = c;
}
/*
* Add a string to the output command table.
*/
void
add_cmd_str(s)
char *s;
{
for ( ; *s != '\0'; s++)
add_cmd_char(*s);
}
/*
* See if we have a special "control" line.
*/
int
control_line(s)
char *s;
{
#define PREFIX(str,pat) (strncmp(str,pat,strlen(pat)) == 0)
if (PREFIX(s, "#line-edit"))
{
currtable = &edittable;
return (1);
}
if (PREFIX(s, "#command"))
{
currtable = &cmdtable;
return (1);
}
if (PREFIX(s, "#env"))
{
currtable = &vartable;
return (1);
}
if (PREFIX(s, "#stop"))
{
add_cmd_char('\0');
add_cmd_char(A_END_LIST);
return (1);
}
return (0);
}
/*
* Output some bytes.
*/
void
static void
fputbytes(fd, buf, len)
FILE *fd;
char *buf;
@ -592,7 +266,7 @@ fputbytes(fd, buf, len)
/*
* Output an integer, in special KRADIX form.
*/
void
static void
fputint(fd, val)
FILE *fd;
unsigned int val;
@ -601,7 +275,7 @@ fputint(fd, val)
if (val >= KRADIX*KRADIX)
{
fprintf(stderr, "error: integer too big (%d > %d)\n",
fprintf(stderr, "error: cannot write %d, max %d\n",
val, KRADIX*KRADIX);
exit(1);
}
@ -611,174 +285,14 @@ fputint(fd, val)
fwrite(&c, sizeof(char), 1, fd);
}
/*
* Find an action, given the name of the action.
*/
int
findaction(actname)
char *actname;
{
int i;
for (i = 0; currtable->names[i].cn_name != NULL; i++)
if (strcmp(currtable->names[i].cn_name, actname) == 0)
return (currtable->names[i].cn_action);
error("unknown action", NULL_PARG);
return (A_INVALID);
}
void
error(s, parg)
char *s;
PARG *parg;
{
fprintf(stderr, "line %d: %s\n", linenum, s);
errors++;
(void) parg;
}
void
parse_cmdline(p)
char *p;
{
int cmdlen;
char *actname;
int action;
char *s;
char c;
/*
* Parse the command string and store it in the current table.
*/
cmdlen = 0;
do
{
s = tstr(&p, 1);
cmdlen += (int) strlen(s);
if (cmdlen > MAX_CMDLEN)
error("command too long", NULL_PARG);
else
add_cmd_str(s);
} while (*p != ' ' && *p != '\t' && *p != '\0');
/*
* Terminate the command string with a null byte.
*/
add_cmd_char('\0');
/*
* Skip white space between the command string
* and the action name.
* Terminate the action name with a null byte.
*/
p = skipsp(p);
if (*p == '\0')
{
error("missing action", NULL_PARG);
return;
}
actname = p;
p = skipnsp(p);
c = *p;
*p = '\0';
/*
* Parse the action name and store it in the current table.
*/
action = findaction(actname);
/*
* See if an extra string follows the action name.
*/
*p = c;
p = skipsp(p);
if (*p == '\0')
{
add_cmd_char(action);
} else
{
/*
* OR the special value A_EXTRA into the action byte.
* Put the extra string after the action byte.
*/
add_cmd_char(action | A_EXTRA);
while (*p != '\0')
add_cmd_str(tstr(&p, 0));
add_cmd_char('\0');
}
}
void
parse_varline(p)
char *p;
{
char *s;
do
{
s = tstr(&p, 0);
add_cmd_str(s);
} while (*p != ' ' && *p != '\t' && *p != '=' && *p != '\0');
/*
* Terminate the variable name with a null byte.
*/
add_cmd_char('\0');
p = skipsp(p);
if (*p++ != '=')
{
error("missing =", NULL_PARG);
return;
}
add_cmd_char(EV_OK|A_EXTRA);
p = skipsp(p);
while (*p != '\0')
{
s = tstr(&p, 0);
add_cmd_str(s);
}
add_cmd_char('\0');
}
/*
* Parse a line from the lesskey file.
*/
void
parse_line(line)
char *line;
{
char *p;
/*
* See if it is a control line.
*/
if (control_line(line))
return;
/*
* Skip leading white space.
* Replace the final newline with a null byte.
* Ignore blank lines and comments.
*/
p = clean_line(line);
if (*p == '\0')
return;
if (currtable == &vartable)
parse_varline(p);
else
parse_cmdline(p);
}
int
main(argc, argv)
int argc;
char *argv[];
{
FILE *desc;
struct lesskey_tables tables;
FILE *out;
char line[1024];
int errors;
#ifdef WIN32
if (getenv("HOME") == NULL)
@ -791,7 +305,7 @@ main(argc, argv)
char *path = getenv("HOMEPATH");
if (drive != NULL && path != NULL)
{
char *env = (char *) calloc(strlen(drive) +
char *env = (char *) ecalloc(strlen(drive) +
strlen(path) + 6, sizeof(char));
strcpy(env, "HOME=");
strcat(env, drive);
@ -805,44 +319,19 @@ main(argc, argv)
* Process command line arguments.
*/
parse_args(argc, argv);
init_tables();
/*
* Open the input file.
*/
if (strcmp(infile, "-") == 0)
desc = stdin;
else if ((desc = fopen(infile, "r")) == NULL)
errors = parse_lesskey(infile, &tables);
if (errors)
{
#if HAVE_PERROR
perror(infile);
#else
fprintf(stderr, "Cannot open %s\n", infile);
#endif
usage();
fprintf(stderr, "%d errors; no output produced\n", errors);
return (1);
}
/*
* Read and parse the input file, one line at a time.
*/
errors = 0;
linenum = 0;
while (fgets(line, sizeof(line), desc) != NULL)
{
++linenum;
parse_line(line);
}
fprintf(stderr, "NOTE: lesskey is deprecated.\n It is no longer necessary to run lesskey,\n when using less version 582 and later.\n");
/*
* Write the output file.
* If no output file was specified, use "$HOME/.less"
*/
if (errors > 0)
{
fprintf(stderr, "%d errors; no output produced\n", errors);
exit(1);
}
if (outfile == NULL)
outfile = getenv("LESSKEY");
if (outfile == NULL)
@ -854,7 +343,7 @@ main(argc, argv)
#else
fprintf(stderr, "Cannot open %s\n", outfile);
#endif
exit(1);
return (1);
}
/* File header */
@ -862,17 +351,17 @@ main(argc, argv)
/* Command key section */
fputbytes(out, cmdsection, sizeof(cmdsection));
fputint(out, cmdtable.pbuffer - cmdtable.buffer);
fputbytes(out, (char *)cmdtable.buffer, cmdtable.pbuffer-cmdtable.buffer);
fputint(out, tables.cmdtable.buf.end);
fputbytes(out, (char *)tables.cmdtable.buf.data, tables.cmdtable.buf.end);
/* Edit key section */
fputbytes(out, editsection, sizeof(editsection));
fputint(out, edittable.pbuffer - edittable.buffer);
fputbytes(out, (char *)edittable.buffer, edittable.pbuffer-edittable.buffer);
fputint(out, tables.edittable.buf.end);
fputbytes(out, (char *)tables.edittable.buf.data, tables.edittable.buf.end);
/* Environment variable section */
fputbytes(out, varsection, sizeof(varsection));
fputint(out, vartable.pbuffer - vartable.buffer);
fputbytes(out, (char *)vartable.buffer, vartable.pbuffer-vartable.buffer);
fputint(out, tables.vartable.buf.end);
fputbytes(out, (char *)tables.vartable.buf.data, tables.vartable.buf.end);
/* File trailer */
fputbytes(out, endsection, sizeof(endsection));

View File

@ -7,6 +7,7 @@
* For more information, see the README file.
*/
#include "xbuf.h"
/*
* Format of a lesskey file:
@ -37,3 +38,26 @@
/* */
#define KRADIX 64
struct lesskey_cmdname
{
char *cn_name;
int cn_action;
};
struct lesskey_table
{
struct lesskey_cmdname *names;
struct xbuffer buf;
int is_var;
};
struct lesskey_tables
{
struct lesskey_table *currtable;
struct lesskey_table cmdtable;
struct lesskey_table edittable;
struct lesskey_table vartable;
};
extern int parse_lesskey(char *infile, struct lesskey_tables *tables);

View File

@ -5,34 +5,21 @@ LESSKEY(1) General Commands Manual LESSKEY(1)
NAME
lesskey - specify key bindings for less
SYNOPSIS
SYNOPSIS (deprecated)
lesskey [-o output] [--] [input]
lesskey [--output=output] [--] [input]
lesskey -V
lesskey --version
DESCRIPTION
Lesskey is used to specify a set of key bindings to be used by less.
The input file is a text file which describes the key bindings. If the
input file is "-", standard input is read. If no input file is speci-
fied, a standard filename is used as the name of the input file, which
depends on the system being used: On Unix systems, "$HOME/.lesskey" is
used; on MS-DOS systems, "$HOME/_lesskey" is used; and on OS/2 systems
"$HOME/lesskey.ini" is used, or "$INIT/lesskey.ini" if $HOME is unde-
fined. The output file is a binary file which is used by less. If no
output file is specified, and the environment variable LESSKEY is set,
the value of LESSKEY is used as the name of the output file. Other-
wise, a standard filename is used as the name of the output file, which
depends on the system being used: On Unix and OS-9 systems,
"$HOME/.less" is used; on MS-DOS systems, "$HOME/_less" is used; and on
OS/2 systems, "$HOME/less.ini" is used, or "$INIT/less.ini" if $HOME is
undefined. If the output file already exists, lesskey will overwrite
it.
The -V or --version option causes lesskey to print its version number
and immediately exit. If -V or --version is present, other options and
arguments are ignored.
SCOPE
This document describes the format of the lesskey source file, which is
used by less version 582 and later. In previous versions of less, a
separate program called lesskey was used to compile the lesskey source
file into a format understood by less. This compilation step is no
longer required and the lesskey program is therefore deprecated al-
though the file format remains supported by less itself.
FILE FORMAT
The input file consists of one or more sections. Each section starts
with a line that identifies the type of section. Possible sections
are:
@ -129,7 +116,6 @@ LESSKEY(1) General Commands Manual LESSKEY(1)
J forw-line-force
K back-line-force
Y back-line-force
d forw-scroll
^D forw-scroll
u back-scroll
@ -143,6 +129,7 @@ LESSKEY(1) General Commands Manual LESSKEY(1)
^B back-screen
\ev back-screen
\kU back-screen
z forw-window
w back-window
\e\40 forw-screen-force
@ -195,7 +182,6 @@ LESSKEY(1) General Commands Manual LESSKEY(1)
& filter
m set-mark
M set-mark-bottom
\em clear-mark
' goto-mark
^X^X goto-mark
@ -209,6 +195,7 @@ LESSKEY(1) General Commands Manual LESSKEY(1)
:x index-file
:d remove-file
- toggle-option
:t toggle-option t
s toggle-option o
_ display-option
@ -274,6 +261,7 @@ LESSKEY(1) General Commands Manual LESSKEY(1)
\t forw-complete
\17 back-complete
\e\t back-complete
^L expand
^V literal
^A literal
@ -358,4 +346,4 @@ LESSKEY(1) General Commands Manual LESSKEY(1)
Version 581.2: 28 Apr 2021 LESSKEY(1)
Version 590: 03 Jun 2021 LESSKEY(1)

View File

@ -1,8 +1,8 @@
'\" t
.TH LESSKEY 1 "Version 581.2: 28 Apr 2021"
.TH LESSKEY 1 "Version 590: 03 Jun 2021"
.SH NAME
lesskey \- specify key bindings for less
.SH SYNOPSIS
.SH "SYNOPSIS (deprecated)"
.B "lesskey [\-o output] [\-\-] [input]"
.br
.B "lesskey [\-\-output=output] [\-\-] [input]"
@ -10,38 +10,27 @@ lesskey \- specify key bindings for less
.B "lesskey \-V"
.br
.B "lesskey \-\-version"
.SH DESCRIPTION
.I Lesskey
is used to specify a set of key bindings to be used by
.IR less .
The input file is a text file which describes the key bindings.
If the input file is "\-", standard input is read.
If no input file is specified, a standard filename is used
as the name of the input file, which depends on the system being used:
On Unix systems, "$HOME/.lesskey" is used;
on MS-DOS systems, "$HOME/_lesskey" is used;
and on OS/2 systems "$HOME/lesskey.ini" is used,
or "$INIT/lesskey.ini" if $HOME is undefined.
The output file is a binary file which is used by
.IR less .
If no output file is specified,
and the environment variable LESSKEY is set,
the value of LESSKEY is used as the name of the output file.
Otherwise, a standard filename is used as the name of the output file,
which depends on the system being used:
On Unix and OS-9 systems, "$HOME/.less" is used;
on MS-DOS systems, "$HOME/_less" is used;
and on OS/2 systems, "$HOME/less.ini" is used,
or "$INIT/less.ini" if $HOME is undefined.
If the output file already exists,
.SH SCOPE
This document describes the format of the
.I lesskey
will overwrite it.
.PP
The \-V or \-\-version option causes
source file, which is used by
.I less
version 582 and later.
In previous versions of
.IR less ,
a separate program called
.I lesskey
to print its version number and immediately exit.
If \-V or \-\-version is present, other options and arguments are ignored.
was used to compile the
.I lesskey
source file into a format understood by
.IR less .
This compilation step is no longer required and the
.I lesskey
program is therefore deprecated although the file format remains supported by
.I less
itself.
.PP
.SH FILE FORMAT
The input file consists of one or more
.I sections.
Each section starts with a line that identifies the type of section.

580
lesskey_parse.c Normal file
View File

@ -0,0 +1,580 @@
/*
* Copyright (C) 1984-2021 Mark Nudelman
*
* You may distribute under the terms of either the GNU General Public
* License or the Less License, as specified in the README file.
*
* For more information, see the README file.
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "lesskey.h"
#include "cmd.h"
#include "xbuf.h"
#include "defines.h"
#define CONTROL(c) ((c)&037)
#define ESC CONTROL('[')
extern void lesskey_parse_error(char *msg);
extern char *homefile(char *filename);
extern void *ecalloc(int count, unsigned int size);
static int linenum;
static int errors;
static char *lesskey_file;
static struct lesskey_cmdname cmdnames[] =
{
{ "back-bracket", A_B_BRACKET },
{ "back-line", A_B_LINE },
{ "back-line-force", A_BF_LINE },
{ "back-screen", A_B_SCREEN },
{ "back-scroll", A_B_SCROLL },
{ "back-search", A_B_SEARCH },
{ "back-window", A_B_WINDOW },
{ "clear-mark", A_CLRMARK },
{ "debug", A_DEBUG },
{ "digit", A_DIGIT },
{ "display-flag", A_DISP_OPTION },
{ "display-option", A_DISP_OPTION },
{ "end", A_GOEND },
{ "end-scroll", A_RRSHIFT },
{ "examine", A_EXAMINE },
{ "filter", A_FILTER },
{ "first-cmd", A_FIRSTCMD },
{ "firstcmd", A_FIRSTCMD },
{ "flush-repaint", A_FREPAINT },
{ "forw-bracket", A_F_BRACKET },
{ "forw-forever", A_F_FOREVER },
{ "forw-until-hilite", A_F_UNTIL_HILITE },
{ "forw-line", A_F_LINE },
{ "forw-line-force", A_FF_LINE },
{ "forw-screen", A_F_SCREEN },
{ "forw-screen-force", A_FF_SCREEN },
{ "forw-scroll", A_F_SCROLL },
{ "forw-search", A_F_SEARCH },
{ "forw-window", A_F_WINDOW },
{ "goto-end", A_GOEND },
{ "goto-end-buffered", A_GOEND_BUF },
{ "goto-line", A_GOLINE },
{ "goto-mark", A_GOMARK },
{ "help", A_HELP },
{ "index-file", A_INDEX_FILE },
{ "invalid", A_UINVALID },
{ "left-scroll", A_LSHIFT },
{ "next-file", A_NEXT_FILE },
{ "next-tag", A_NEXT_TAG },
{ "noaction", A_NOACTION },
{ "no-scroll", A_LLSHIFT },
{ "percent", A_PERCENT },
{ "pipe", A_PIPE },
{ "prev-file", A_PREV_FILE },
{ "prev-tag", A_PREV_TAG },
{ "quit", A_QUIT },
{ "remove-file", A_REMOVE_FILE },
{ "repaint", A_REPAINT },
{ "repaint-flush", A_FREPAINT },
{ "repeat-search", A_AGAIN_SEARCH },
{ "repeat-search-all", A_T_AGAIN_SEARCH },
{ "reverse-search", A_REVERSE_SEARCH },
{ "reverse-search-all", A_T_REVERSE_SEARCH },
{ "right-scroll", A_RSHIFT },
{ "set-mark", A_SETMARK },
{ "set-mark-bottom", A_SETMARKBOT },
{ "shell", A_SHELL },
{ "status", A_STAT },
{ "toggle-flag", A_OPT_TOGGLE },
{ "toggle-option", A_OPT_TOGGLE },
{ "undo-hilite", A_UNDO_SEARCH },
{ "clear-search", A_CLR_SEARCH },
{ "version", A_VERSION },
{ "visual", A_VISUAL },
{ NULL, 0 }
};
static struct lesskey_cmdname editnames[] =
{
{ "back-complete", EC_B_COMPLETE },
{ "backspace", EC_BACKSPACE },
{ "delete", EC_DELETE },
{ "down", EC_DOWN },
{ "end", EC_END },
{ "expand", EC_EXPAND },
{ "forw-complete", EC_F_COMPLETE },
{ "home", EC_HOME },
{ "insert", EC_INSERT },
{ "invalid", EC_UINVALID },
{ "kill-line", EC_LINEKILL },
{ "abort", EC_ABORT },
{ "left", EC_LEFT },
{ "literal", EC_LITERAL },
{ "right", EC_RIGHT },
{ "up", EC_UP },
{ "word-backspace", EC_W_BACKSPACE },
{ "word-delete", EC_W_DELETE },
{ "word-left", EC_W_LEFT },
{ "word-right", EC_W_RIGHT },
{ NULL, 0 }
};
/*
* Print a parse error message.
*/
static void
parse_error(s1, s2)
char *s1;
char *s2;
{
char buf[1024];
++errors;
snprintf(buf, sizeof(buf), "%s: line %d: %s%s", lesskey_file, linenum, s1, s2);
lesskey_parse_error(buf);
}
/*
* Initialize lesskey_tables.
*/
static void
init_tables(tables)
struct lesskey_tables *tables;
{
tables->currtable = &tables->cmdtable;
tables->cmdtable.names = cmdnames;
tables->cmdtable.is_var = 0;
xbuf_init(&tables->cmdtable.buf);
tables->edittable.names = editnames;
tables->edittable.is_var = 0;
xbuf_init(&tables->edittable.buf);
tables->vartable.names = NULL;
tables->vartable.is_var = 1;
xbuf_init(&tables->vartable.buf);
}
/*
* Parse one character of a string.
*/
static char *
tstr(pp, xlate)
char **pp;
int xlate;
{
char *p;
char ch;
int i;
static char buf[10];
static char tstr_control_k[] =
{ SK_SPECIAL_KEY, SK_CONTROL_K, 6, 1, 1, 1, '\0' };
p = *pp;
switch (*p)
{
case '\\':
++p;
switch (*p)
{
case '0': case '1': case '2': case '3':
case '4': case '5': case '6': case '7':
/*
* Parse an octal number.
*/
ch = 0;
i = 0;
do
ch = 8*ch + (*p - '0');
while (*++p >= '0' && *p <= '7' && ++i < 3);
*pp = p;
if (xlate && ch == CONTROL('K'))
return tstr_control_k;
buf[0] = ch;
buf[1] = '\0';
return (buf);
case 'b':
*pp = p+1;
return ("\b");
case 'e':
*pp = p+1;
buf[0] = ESC;
buf[1] = '\0';
return (buf);
case 'n':
*pp = p+1;
return ("\n");
case 'r':
*pp = p+1;
return ("\r");
case 't':
*pp = p+1;
return ("\t");
case 'k':
if (xlate)
{
switch (*++p)
{
case 'u': ch = SK_UP_ARROW; break;
case 'd': ch = SK_DOWN_ARROW; break;
case 'r': ch = SK_RIGHT_ARROW; break;
case 'l': ch = SK_LEFT_ARROW; break;
case 'U': ch = SK_PAGE_UP; break;
case 'D': ch = SK_PAGE_DOWN; break;
case 'h': ch = SK_HOME; break;
case 'e': ch = SK_END; break;
case 'x': ch = SK_DELETE; break;
default: { char buf[2]; buf[0] = *p; buf[1] = '\0';
parse_error("illegal escape sequence \\k", buf);
*pp = p+1;
return (""); }
}
*pp = p+1;
buf[0] = SK_SPECIAL_KEY;
buf[1] = ch;
buf[2] = 6;
buf[3] = 1;
buf[4] = 1;
buf[5] = 1;
buf[6] = '\0';
return (buf);
}
/* FALLTHRU */
default:
/*
* Backslash followed by any other char
* just means that char.
*/
*pp = p+1;
buf[0] = *p;
buf[1] = '\0';
if (xlate && buf[0] == CONTROL('K'))
return tstr_control_k;
return (buf);
}
case '^':
/*
* Caret means CONTROL.
*/
*pp = p+2;
buf[0] = CONTROL(p[1]);
buf[1] = '\0';
if (xlate && buf[0] == CONTROL('K'))
return tstr_control_k;
return (buf);
}
*pp = p+1;
buf[0] = *p;
buf[1] = '\0';
if (xlate && buf[0] == CONTROL('K'))
return tstr_control_k;
return (buf);
}
static int
issp(ch)
char ch;
{
return (ch == ' ' || ch == '\t');
}
/*
* Skip leading spaces in a string.
*/
static char *
skipsp(s)
char *s;
{
while (issp(*s))
s++;
return (s);
}
/*
* Skip non-space characters in a string.
*/
static char *
skipnsp(s)
char *s;
{
while (*s != '\0' && !issp(*s))
s++;
return (s);
}
/*
* Clean up an input line:
* strip off the trailing newline & any trailing # comment.
*/
static char *
clean_line(s)
char *s;
{
int i;
s = skipsp(s);
for (i = 0; s[i] != '\0' && s[i] != '\n' && s[i] != '\r'; i++)
if (s[i] == '#' && (i == 0 || s[i-1] != '\\'))
break;
s[i] = '\0';
return (s);
}
/*
* Add a byte to the output command table.
*/
static void
add_cmd_char(c, tables)
int c;
struct lesskey_tables *tables;
{
xbuf_add(&tables->currtable->buf, c);
}
/*
* Add a string to the output command table.
*/
static void
add_cmd_str(s, tables)
char *s;
struct lesskey_tables *tables;
{
for ( ; *s != '\0'; s++)
add_cmd_char(*s, tables);
}
/*
* See if we have a special "control" line.
*/
static int
control_line(s, tables)
char *s;
struct lesskey_tables *tables;
{
#define PREFIX(str,pat) (strncmp(str,pat,strlen(pat)) == 0)
if (PREFIX(s, "#line-edit"))
{
tables->currtable = &tables->edittable;
return (1);
}
if (PREFIX(s, "#command"))
{
tables->currtable = &tables->cmdtable;
return (1);
}
if (PREFIX(s, "#env"))
{
tables->currtable = &tables->vartable;
return (1);
}
if (PREFIX(s, "#stop"))
{
add_cmd_char('\0', tables);
add_cmd_char(A_END_LIST, tables);
return (1);
}
return (0);
}
/*
* Find an action, given the name of the action.
*/
static int
findaction(actname, tables)
char *actname;
struct lesskey_tables *tables;
{
int i;
for (i = 0; tables->currtable->names[i].cn_name != NULL; i++)
if (strcmp(tables->currtable->names[i].cn_name, actname) == 0)
return (tables->currtable->names[i].cn_action);
parse_error("unknown action: ", actname);
return (A_INVALID);
}
/*
* Parse a line describing one key binding, of the form
* KEY ACTION [EXTRA]
* where KEY is the user key sequence, ACTION is the
* resulting less action, and EXTRA is an "extra" user
* key sequence injected after the action.
*/
static void
parse_cmdline(p, tables)
char *p;
struct lesskey_tables *tables;
{
char *actname;
int action;
char *s;
char c;
/*
* Parse the command string and store it in the current table.
*/
do
{
s = tstr(&p, 1);
add_cmd_str(s, tables);
} while (*p != '\0' && !issp(*p));
/*
* Terminate the command string with a null byte.
*/
add_cmd_char('\0', tables);
/*
* Skip white space between the command string
* and the action name.
* Terminate the action name with a null byte.
*/
p = skipsp(p);
if (*p == '\0')
{
parse_error("missing action", "");
return;
}
actname = p;
p = skipnsp(p);
c = *p;
*p = '\0';
/*
* Parse the action name and store it in the current table.
*/
action = findaction(actname, tables);
/*
* See if an extra string follows the action name.
*/
*p = c;
p = skipsp(p);
if (*p == '\0')
{
add_cmd_char(action, tables);
} else
{
/*
* OR the special value A_EXTRA into the action byte.
* Put the extra string after the action byte.
*/
add_cmd_char(action | A_EXTRA, tables);
while (*p != '\0')
add_cmd_str(tstr(&p, 0), tables);
add_cmd_char('\0', tables);
}
}
/*
* Parse a variable definition line, of the form
* NAME = VALUE
*/
static void
parse_varline(line, tables)
char *line;
struct lesskey_tables *tables;
{
char *s;
char *p = line;
do
{
s = tstr(&p, 0);
add_cmd_str(s, tables);
} while (*p != '\0' && !issp(*p) && *p != '=');
/*
* Terminate the variable name with a null byte.
*/
add_cmd_char('\0', tables);
p = skipsp(p);
if (*p++ != '=')
{
parse_error("missing = in: ", line);
return;
}
add_cmd_char(EV_OK|A_EXTRA, tables);
p = skipsp(p);
while (*p != '\0')
{
s = tstr(&p, 0);
add_cmd_str(s, tables);
}
add_cmd_char('\0', tables);
}
/*
* Parse a line from the lesskey file.
*/
static void
parse_line(line, tables)
char *line;
struct lesskey_tables *tables;
{
char *p;
/*
* See if it is a control line.
*/
if (control_line(line, tables))
return;
/*
* Skip leading white space.
* Replace the final newline with a null byte.
* Ignore blank lines and comments.
*/
p = clean_line(line);
if (*p == '\0')
return;
if (tables->currtable->is_var)
parse_varline(p, tables);
else
parse_cmdline(p, tables);
}
/*
* Parse a lesskey source file and store result in tables.
*/
int
parse_lesskey(infile, tables)
char *infile;
struct lesskey_tables *tables;
{
FILE *desc;
char line[1024];
if (infile == NULL)
infile = homefile(DEF_LESSKEYINFILE);
lesskey_file = infile;
init_tables(tables);
errors = 0;
linenum = 0;
/*
* Open the input file.
*/
if (strcmp(infile, "-") == 0)
desc = stdin;
else if ((desc = fopen(infile, "r")) == NULL)
{
/* parse_error("cannot open lesskey file ", infile); */
return (-1);
}
/*
* Read and parse the input file, one line at a time.
*/
while (fgets(line, sizeof(line), desc) != NULL)
{
++linenum;
parse_line(line, tables);
}
return (errors);
}

85
line.c
View File

@ -33,11 +33,8 @@ static struct {
int pfx_end; /* Number of chars in pfx */
} linebuf;
static struct {
char *buf;
int size;
int end;
} shifted_ansi;
struct xbuffer shifted_ansi;
struct xbuffer last_ansi;
public int size_linebuf = 0; /* Size of line buffer (and attr buffer) */
static struct ansi_state *line_ansi = NULL;
@ -58,6 +55,7 @@ static LWCHAR pendc;
static POSITION pendpos;
static char *end_ansi_chars;
static char *mid_ansi_chars;
static int in_hilite;
static int attr_swidth LESSPARAMS ((int a));
static int attr_ewidth LESSPARAMS ((int a));
@ -131,8 +129,8 @@ init_line(VOID_PARAM)
linebuf.buf = (char *) ecalloc(LINEBUF_SIZE, sizeof(char));
linebuf.attr = (int *) ecalloc(LINEBUF_SIZE, sizeof(int));
size_linebuf = LINEBUF_SIZE;
shifted_ansi.buf = NULL;
shifted_ansi.size = 0;
xbuf_init(&shifted_ansi);
xbuf_init(&last_ansi);
}
/*
@ -222,7 +220,9 @@ prewind(VOID_PARAM)
mbc_buf_len = 0;
is_null_line = 0;
pendc = '\0';
shifted_ansi.end = 0;
in_hilite = 0;
xbuf_reset(&shifted_ansi);
xbuf_reset(&last_ansi);
}
/*
@ -354,26 +354,6 @@ line_pfx_width(VOID_PARAM)
return width;
}
/*
* Add char to the shifted_ansi buffer.
*/
static void
add_ansi(ch)
char ch;
{
if (shifted_ansi.end == shifted_ansi.size)
{
/* Expand shifted_ansi buffer. */
int size = (shifted_ansi.size == 0) ? 8 : shifted_ansi.size * 2;
char *buf = (char *) ecalloc(size, sizeof(char));
memcpy(buf, shifted_ansi.buf, shifted_ansi.size);
if (shifted_ansi.buf != NULL) free(shifted_ansi.buf);
shifted_ansi.buf = buf;
shifted_ansi.size = size;
}
shifted_ansi.buf[shifted_ansi.end++] = ch;
}
/*
* Shift line left so that the last char is just to the left
* of the first visible column.
@ -384,7 +364,7 @@ pshift_all(VOID_PARAM)
int i;
for (i = linebuf.print; i < linebuf.end; i++)
if (linebuf.attr[i] == AT_ANSI)
add_ansi(linebuf.buf[i]);
xbuf_add(&shifted_ansi, linebuf.buf[i]);
linebuf.end = linebuf.print;
end_column = linebuf.pfx_end;
}
@ -676,6 +656,7 @@ store_char(ch, a, rep, pos)
#if HILITE_SEARCH
{
int matches;
int resend_last = 0;
int hl_attr = is_hilited_attr(pos, pos+1, 0, &matches);
if (hl_attr)
{
@ -689,6 +670,23 @@ store_char(ch, a, rep, pos)
highest_hilite = pos;
a |= hl_attr;
}
in_hilite = 1;
} else
{
if (in_hilite)
{
/*
* This is the first non-hilited char after a hilite.
* Resend the last ANSI seq to restore color.
*/
resend_last = 1;
}
in_hilite = 0;
}
if (resend_last)
{
for (i = 0; i < last_ansi.end; i++)
STORE_CHAR(last_ansi.data[i], AT_ANSI, NULL, pos);
}
}
#endif
@ -731,8 +729,8 @@ store_char(ch, a, rep, pos)
{
/* Copy shifted ANSI sequences to beginning of line. */
for (i = 0; i < shifted_ansi.end; i++)
add_linebuf(shifted_ansi.buf[i], AT_ANSI, 0);
shifted_ansi.end = 0;
add_linebuf(shifted_ansi.data[i], AT_ANSI, 0);
xbuf_reset(&shifted_ansi);
}
/* Add the char to the buf, even if we will left-shift it next. */
inc_end_column(w);
@ -743,12 +741,16 @@ store_char(ch, a, rep, pos)
{
/* We haven't left-shifted enough yet. */
if (a == AT_ANSI)
add_ansi(ch); /* Save ANSI attributes */
xbuf_add(&shifted_ansi, ch); /* Save ANSI attributes */
if (linebuf.end > linebuf.print)
{
/* Shift left enough to put last byte of this char at print-1. */
memcpy(&linebuf.buf[0], &linebuf.buf[replen], linebuf.print);
memcpy(&linebuf.attr[0], &linebuf.attr[replen], linebuf.print);
int i;
for (i = 0; i < linebuf.print; i++)
{
linebuf.buf[i] = linebuf.buf[i+replen];
linebuf.attr[i] = linebuf.attr[i+replen];
}
linebuf.end -= replen;
cshift += w;
/*
@ -954,16 +956,18 @@ store_ansi(ch, rep, pos)
switch (ansi_step(line_ansi, ch))
{
case ANSI_MID:
STORE_CHAR(ch, AT_ANSI, rep, pos);
if (!in_hilite)
STORE_CHAR(ch, AT_ANSI, rep, pos);
break;
case ANSI_END:
STORE_CHAR(ch, AT_ANSI, rep, pos);
if (!in_hilite)
STORE_CHAR(ch, AT_ANSI, rep, pos);
ansi_done(line_ansi);
line_ansi = NULL;
break;
case ANSI_ERR: {
/* Remove whole unrecognized sequence. */
char *start = (cshift < hshift) ? shifted_ansi.buf : linebuf.buf;
char *start = (cshift < hshift) ? shifted_ansi.data : linebuf.buf;
int *end = (cshift < hshift) ? &shifted_ansi.end : &linebuf.end;
char *p = start + *end;
LWCHAR bch;
@ -1006,10 +1010,17 @@ do_append(ch, rep, pos)
int a = AT_NORMAL;
if (ctldisp == OPT_ONPLUS && line_ansi == NULL)
{
line_ansi = ansi_start(ch);
if (line_ansi != NULL)
xbuf_reset(&last_ansi);
}
if (line_ansi != NULL)
{
xbuf_add(&last_ansi, ch);
return store_ansi(ch, rep, pos);
}
if (ch == '\b')
return store_bs(ch, rep, pos);

View File

@ -469,3 +469,26 @@ currline(where)
linenum--;
return (linenum);
}
/*
* Scan entire file, counting line numbers.
*/
public void
scan_eof(VOID_PARAM)
{
POSITION pos = 0;
LINENUM linenum = 0;
if (ch_seek(0))
return;
ierror("Determining length of file", NULL_PARG);
while (pos != NULL_POSITION)
{
/* For efficiency, only add one every 256 line numbers. */
if ((linenum++ % 256) == 0)
add_lnum(linenum, pos);
pos = forw_raw_line(pos, (char **)NULL, (int *)NULL);
if (ABORT_SIGS())
break;
}
}

View File

@ -58,6 +58,7 @@ extern int less_is_more;
extern int linenum_width;
extern int status_col_width;
extern int use_color;
extern int want_filesize;
#if LOGFILE
extern char *namelogfile;
extern int force_logfile;
@ -163,7 +164,7 @@ opt_j(type, s)
char *s;
{
PARG parg;
char buf[16];
char buf[24];
int len;
int err;
@ -199,7 +200,7 @@ opt_j(type, s)
} else
{
sprintf(buf, ".%06ld", jump_sline_fraction);
SNPRINTF1(buf, sizeof(buf), ".%06ld", jump_sline_fraction);
len = (int) strlen(buf);
while (len > 2 && buf[len-1] == '0')
len--;
@ -228,7 +229,7 @@ opt_shift(type, s)
char *s;
{
PARG parg;
char buf[16];
char buf[24];
int len;
int err;
@ -264,7 +265,7 @@ opt_shift(type, s)
} else
{
sprintf(buf, ".%06ld", shift_count_fraction);
SNPRINTF1(buf, sizeof(buf), ".%06ld", shift_count_fraction);
len = (int) strlen(buf);
while (len > 2 && buf[len-1] == '0')
len--;
@ -275,6 +276,7 @@ opt_shift(type, s)
break;
}
}
public void
calc_shift_count(VOID_PARAM)
{
@ -302,7 +304,28 @@ opt_k(type, s)
break;
}
}
#endif
#if HAVE_LESSKEYSRC
public void
opt_ks(type, s)
int type;
char *s;
{
PARG parg;
switch (type)
{
case INIT:
if (lesskey_src(s, 0))
{
parg.p_string = s;
error("Cannot use lesskey source file \"%s\"", &parg);
}
break;
}
}
#endif /* HAVE_LESSKEYSRC */
#endif /* USERFILE */
#if TAGS
/*
@ -518,9 +541,8 @@ opt__V(type, s)
putstr(pattern_lib_name());
putstr(" regular expressions)\n");
{
char constant *copyright = "Copyright (C) 1984-2021 Mark Nudelman\n\n";
if (copyright[0] == '@')
copyright = "Copyright (C) 1984 Mark Nudelman\n\n";
char constant *copyright =
"Copyright (C) 1984-2021 Mark Nudelman\n\n";
putstr(copyright);
}
if (version[strlen(version)-1] == 'x')
@ -590,7 +612,7 @@ color_from_namechar(namechar)
{
switch (namechar)
{
case 'A': return AT_COLOR_ATTN;
case 'W': case 'A': return AT_COLOR_ATTN;
case 'B': return AT_COLOR_BIN;
case 'C': return AT_COLOR_CTRL;
case 'E': return AT_COLOR_ERROR;
@ -940,6 +962,27 @@ opt_status_col_width(type, s)
}
}
/*
* Handler for the --file-size option.
*/
/*ARGSUSED*/
public void
opt_filesize(type, s)
int type;
char *s;
{
switch (type)
{
case INIT:
case TOGGLE:
if (want_filesize && curr_ifile != NULL && ch_length() == NULL_POSITION)
scan_eof();
break;
case QUERY:
break;
}
}
#if LESSTEST
/*
* Handler for the --tty option.

View File

@ -63,6 +63,7 @@ public int linenum_width; /* Width of line numbers */
public int status_col_width; /* Width of status column */
public int incr_search; /* Incremental search */
public int use_color; /* Use UI color */
public int want_filesize; /* */
#if HILITE_SEARCH
public int hilite_search; /* Highlight matched search patterns? */
#endif
@ -90,6 +91,9 @@ static struct optname j_optname = { "jump-target", NULL };
static struct optname J__optname = { "status-column", NULL };
#if USERFILE
static struct optname k_optname = { "lesskey-file", NULL };
#if HAVE_LESSKEYSRC
static struct optname ks_optname = { "lesskey-src", NULL };
#endif /* HAVE_LESSKEYSRC */
#endif
static struct optname K__optname = { "quit-on-intr", NULL };
static struct optname L__optname = { "no-lessopen", NULL };
@ -134,6 +138,7 @@ static struct optname linenum_width_optname = { "line-num-width", NULL };
static struct optname status_col_width_optname = { "status-col-width", NULL };
static struct optname incr_search_optname = { "incsearch", NULL };
static struct optname use_color_optname = { "use-color", NULL };
static struct optname want_filesize_optname = { "file-size", NULL };
#if LESSTEST
static struct optname ttyin_name_optname = { "tty", NULL };
static struct optname rstat_optname = { "rstat", NULL };
@ -274,6 +279,12 @@ static struct loption option[] =
STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_k,
{ NULL, NULL, NULL }
},
#if HAVE_LESSKEYSRC
{ OLETTER_NONE, &ks_optname,
STRING|NO_TOGGLE|NO_QUERY, 0, NULL, opt_ks,
{ NULL, NULL, NULL }
},
#endif /* HAVE_LESSKEYSRC */
#endif
{ 'K', &K__optname,
BOOL, OPT_OFF, &quit_on_intr, NULL,
@ -337,8 +348,8 @@ static struct loption option[] =
TRIPLE|REPAINT, OPT_OFF, &ctldisp, NULL,
{
"Display control characters as ^X",
"Display control characters directly",
"Display control characters directly, processing ANSI sequences"
"Display control characters directly (not recommended)",
"Display ANSI sequences directly, other control characters as ^X"
}
},
{ 's', &s_optname,
@ -543,6 +554,14 @@ static struct loption option[] =
NULL
}
},
{ OLETTER_NONE, &want_filesize_optname,
BOOL|REPAINT, OPT_OFF, &want_filesize, opt_filesize,
{
"Don't get size of each file",
"Get size of each file",
NULL
}
},
#if LESSTEST
{ OLETTER_NONE, &ttyin_name_optname,
STRING|NO_TOGGLE, 0, NULL, opt_ttyin_name,

View File

@ -431,11 +431,7 @@ putchr(c)
ubuf_len = 0;
}
#endif
if (need_clr)
{
need_clr = 0;
clear_bot();
}
clear_bot_if_needed();
#if MSDOS_COMPILER
if (c == '\n' && is_tty)
{
@ -459,6 +455,15 @@ putchr(c)
return (c);
}
public void
clear_bot_if_needed(VOID_PARAM)
{
if (!need_clr)
return;
need_clr = 0;
clear_bot();
}
/*
* Output a string.
*/

View File

@ -843,10 +843,10 @@ scrsize(VOID_PARAM)
#endif
#endif
if ((s = lgetenv("LINES")) != NULL)
sc_height = atoi(s);
else if (sys_height > 0)
if (sys_height > 0)
sc_height = sys_height;
else if ((s = lgetenv("LINES")) != NULL)
sc_height = atoi(s);
#if !MSDOS_COMPILER
else if ((n = ltgetnum("li")) > 0)
sc_height = n;
@ -854,10 +854,10 @@ scrsize(VOID_PARAM)
if (sc_height <= 0)
sc_height = DEF_SC_HEIGHT;
if ((s = lgetenv("COLUMNS")) != NULL)
sc_width = atoi(s);
else if (sys_width > 0)
if (sys_width > 0)
sc_width = sys_width;
else if ((s = lgetenv("COLUMNS")) != NULL)
sc_width = atoi(s);
#if !MSDOS_COMPILER
else if ((n = ltgetnum("co")) > 0)
sc_width = n;
@ -1707,6 +1707,7 @@ deinit_mouse(VOID_PARAM)
public void
init(VOID_PARAM)
{
clear_bot_if_needed();
#if !MSDOS_COMPILER
if (!(quit_if_one_screen && one_screen))
{
@ -2526,7 +2527,7 @@ tput_fmt(fmt, color, f_putc)
int color;
int (*f_putc)(int);
{
char buf[16];
char buf[32];
if (color == attrcolor)
return;
SNPRINTF1(buf, sizeof(buf), fmt, color);

18
tags.c
View File

@ -272,6 +272,7 @@ findctag(tag)
char *tag;
{
char *p;
char *q;
FILE *f;
int taglen;
LINENUM taglinenum;
@ -352,17 +353,24 @@ findctag(tag)
search_char = *p++;
if (*p == '^')
p++;
tagpattern = p;
tagpattern = q = p;
while (*p != search_char && *p != '\0')
{
if (*p == '\\')
p++;
p++;
if (q != p)
{
*q++ = *p++;
} else
{
q++;
p++;
}
}
tagendline = (p[-1] == '$');
tagendline = (q[-1] == '$');
if (tagendline)
p--;
*p = '\0';
q--;
*q = '\0';
}
tp = maketagent(tag, tagfile, taglinenum, tagpattern, tagendline);
TAG_INS(tp);

View File

@ -919,7 +919,18 @@ v578 2/9/21 Doc
v579 2/14/21 Fix double-width char bugs and non-match search crash.
v580 3/2/21 Some color fixes; fix compiler warnings; some lesstest support.
v581 4/6/21 Ignore SIGTSTP in secure mode; don't print "skipping" when filtering.
v581.2 4/28/21 Fix failure to deinit mouse.
v582 4/21/21 Less now reads lesskey source file rather than binary;
fix bug in finding tags with backslashes.
v583 4/21/21 Use XDG_CONFIG_HOME and XDG_DATA_HOME to find files.
v584 4/30/21 Add --file-size option.
v585 5/2/21 Allow color desc W per man page.
v586 5/7/21 Doc changes.
v587 5/27/21 Fix --with-secure; fix --file-size message on Windows;
fix colored search hilite in colored text; don't exit
if -F and screen is resized; fix memcpy usage.
v588 5/27/21 Fix release.
v589 5/29/21 Copyright & build changes.
v590 6/3/21 Fix non-autoconf Makefiles.
*/
char version[] = "581.2";
char version[] = "590";

52
xbuf.c Normal file
View File

@ -0,0 +1,52 @@
#include "less.h"
#include "xbuf.h"
/*
* Initialize an expandable text buffer.
*/
public void
xbuf_init(xbuf)
struct xbuffer *xbuf;
{
xbuf->data = NULL;
xbuf->size = xbuf->end = 0;
}
public void
xbuf_deinit(xbuf)
struct xbuffer *xbuf;
{
if (xbuf->data != NULL)
free(xbuf->data);
xbuf_init(xbuf);
}
public void
xbuf_reset(xbuf)
struct xbuffer *xbuf;
{
xbuf->end = 0;
}
/*
* Add a char to an expandable text buffer.
*/
public void
xbuf_add(xbuf, ch)
struct xbuffer *xbuf;
char ch;
{
if (xbuf->end >= xbuf->size)
{
char *data;
xbuf->size = (xbuf->size == 0) ? 16 : xbuf->size * 2;
data = (char *) ecalloc(xbuf->size, sizeof(char));
if (xbuf->data != NULL)
{
memcpy(data, xbuf->data, xbuf->end);
free(xbuf->data);
}
xbuf->data = data;
}
xbuf->data[xbuf->end++] = ch;
}

15
xbuf.h Normal file
View File

@ -0,0 +1,15 @@
#ifndef XBUF_H_
#define XBUF_H_
struct xbuffer
{
char *data;
int end;
int size;
};
void xbuf_init(struct xbuffer *xbuf);
void xbuf_reset(struct xbuffer *xbuf);
void xbuf_add(struct xbuffer *xbuf, char ch);
#endif