nnn

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit fe87551742b679f2adc2d912ba0ecf3bb9987a8e
parent 2fbf5f0da302f9861f82fcbd86ba7bbe8dbc0202
Author: Arun Prakash Jana <engineerarun@gmail.com>
Date:   Sun,  4 May 2025 13:21:01 +0530

Support PCRE2, remove PCRE1 support (no longer being developed)

To compile-in:

    make O_PCRE2=1

Diffstat:
MMakefile | 8++++----
MREADME.md | 2+-
Mnnn.1 | 2+-
Msrc/nnn.c | 85+++++++++++++++++++++++++++++++++++++++++++++----------------------------------
4 files changed, 54 insertions(+), 43 deletions(-)

diff --git a/Makefile b/Makefile @@ -13,7 +13,7 @@ CFLAGS_OPTIMIZATION ?= -O3 O_DEBUG := 0 # debug binary O_NORL := 0 # no readline support -O_PCRE := 0 # link with PCRE library +O_PCRE2 := 0 # link with PCRE2 library O_NOLC := 0 # no locale support O_NOMOUSE := 0 # no mouse support O_NOBATCH := 0 # no built-in batch renamer @@ -63,9 +63,9 @@ else LDLIBS += -lreadline endif -ifeq ($(strip $(O_PCRE)),1) - CPPFLAGS += -DPCRE - LDLIBS += -lpcre +ifeq ($(strip $(O_PCRE2)),1) + CPPFLAGS += -DPCRE2 + LDLIBS += -lpcre2-8 endif ifeq ($(strip $(O_NOLC)),1) diff --git a/README.md b/README.md @@ -68,7 +68,7 @@ Runs on the Pi, [Termux](https://www.youtube.com/embed/AbaauM7gUJw) (Android), L - Proceed to next file on file open and selection - Search - Instant filtering with *search-as-you-type* - - Regex (POSIX/PCRE) and string (default) filters + - Regex (POSIX/PCRE2) and string (default) filters - Subtree search plugin to open or edit files - Sort - Ordered pure numeric names by default (visit `/proc`) diff --git a/nnn.1 b/nnn.1 @@ -261,7 +261,7 @@ Common regex use cases: .br (3) Use '.*' to match any character (\fIsort of\fR fuzzy search). .br -(4) Exclude filenames having 'nnn' (compiled with PCRE lib): '^(?!nnn)' +(4) Exclude filenames having 'nnn' (compiled with PCRE2 lib): '^(?!nnn)' .Pp In the \fItype-to-nav\fR mode directories are opened in filter mode, allowing continuous navigation. diff --git a/src/nnn.c b/src/nnn.c @@ -87,8 +87,9 @@ #include <readline/history.h> #include <readline/readline.h> #endif -#ifdef PCRE -#include <pcre.h> +#ifdef PCRE2 +#define PCRE2_CODE_UNIT_WIDTH 8 +#include <pcre2.h> #else #include <regex.h> #endif @@ -332,8 +333,8 @@ typedef struct { } kv; typedef struct { -#ifdef PCRE - const pcre *pcrex; +#ifdef PCRE2 + const pcre2_code *pcre2x; #else const regex_t *regex; #endif @@ -485,8 +486,8 @@ static uchar_t blk_shift = BLK_SHIFT_512; #ifndef NOMOUSE static int middle_click_key; #endif -#ifdef PCRE -static pcre *archive_pcre; +#ifdef PCRE2 +static pcre2_code *archive_pcre2; #else static regex_t archive_re; #endif @@ -2995,22 +2996,21 @@ static int xstrverscasecmp(const char * const s1, const char * const s2) static int (*namecmpfn)(const char * const s1, const char * const s2) = &xstricmp; static char * (*fnstrstr)(const char *haystack, const char *needle) = &strcasestr; -#ifdef PCRE +#ifdef PCRE2 static const unsigned char *tables; -static int pcreflags = PCRE_NO_AUTO_CAPTURE | PCRE_EXTENDED | PCRE_CASELESS | PCRE_UTF8; +static int pcre2flags = PCRE2_NO_AUTO_CAPTURE | PCRE2_EXTENDED | PCRE2_CASELESS | PCRE2_UTF; #else static int regflags = REG_NOSUB | REG_EXTENDED | REG_ICASE; #endif -#ifdef PCRE -static int setfilter(pcre **pcrex, const char *filter) +#ifdef PCRE2 +static int setfilter(pcre2_code **pcre2x, const char *filter) { - const char *errstr = NULL; - int erroffset = 0; + int errcode; + PCRE2_SIZE erroffset; - *pcrex = pcre_compile(filter, pcreflags, &errstr, &erroffset, tables); - - return errstr ? -1 : 0; + *pcre2x = pcre2_compile((PCRE2_SPTR)filter, PCRE2_ZERO_TERMINATED, pcre2flags, &errcode, &erroffset, NULL); + return *pcre2x ? 0 : -1; } #else static int setfilter(regex_t *regex, const char *filter) @@ -3021,8 +3021,12 @@ static int setfilter(regex_t *regex, const char *filter) static int visible_re(const fltrexp_t *fltrexp, const char *fname) { -#ifdef PCRE - return pcre_exec(fltrexp->pcrex, NULL, fname, xstrlen(fname), 0, 0, NULL, 0) == 0; +#ifdef PCRE2 + pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(fltrexp->pcre2x, NULL); + int r = pcre2_match(fltrexp->pcre2x, (PCRE2_SPTR)fname, xstrlen(fname), 0, 0, match_data, NULL); + + pcre2_match_data_free(match_data); + return r > 0; #else return regexec(fltrexp->regex, fname, 0, NULL, 0) == 0; #endif @@ -3304,14 +3308,14 @@ static inline void swap_ent(int id1, int id2) *pdent2 = *(&_dent); } -#ifdef PCRE -static int fill(const char *fltr, pcre *pcrex) +#ifdef PCRE2 +static int fill(const char *fltr, pcre2_code *pcre2x) #else static int fill(const char *fltr, regex_t *re) #endif { -#ifdef PCRE - fltrexp_t fltrexp = { .pcrex = pcrex, .str = fltr }; +#ifdef PCRE2 + fltrexp_t fltrexp = { .pcre2x = pcre2x, .str = fltr }; #else fltrexp_t fltrexp = { .regex = re, .str = fltr }; #endif @@ -3332,17 +3336,17 @@ static int fill(const char *fltr, regex_t *re) static int matches(const char *fltr) { -#ifdef PCRE - pcre *pcrex = NULL; +#ifdef PCRE2 + pcre2_code *pcre2x = NULL; /* Search filter */ - if (cfg.regex && setfilter(&pcrex, fltr)) + if (cfg.regex && setfilter(&pcre2x, fltr)) return -1; - ndents = fill(fltr, pcrex); + ndents = fill(fltr, pcre2x); if (cfg.regex) - pcre_free(pcrex); + pcre2_code_free(pcre2x); #else regex_t re; @@ -3510,8 +3514,8 @@ static int filterentries(char *path, char *lastname) /* Toggle case-sensitivity */ if (*ch == CASE) { fnstrstr = (fnstrstr == &strcasestr) ? &strstr : &strcasestr; -#ifdef PCRE - pcreflags ^= PCRE_CASELESS; +#ifdef PCRE2 + pcre2flags ^= PCRE2_CASELESS; #else regflags ^= REG_ICASE; #endif @@ -7322,9 +7326,16 @@ nochange: /* Get the extension for regex match */ tmp = xextension(pent->name, pent->nlen - 1); -#ifdef PCRE - if (tmp && !pcre_exec(archive_pcre, NULL, tmp, - pent->nlen - (tmp - pent->name) - 1, 0, 0, NULL, 0)) { +#ifdef PCRE2 + if (tmp) { + pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(archive_pcre2, NULL); + + r = pcre2_match(archive_pcre2, (PCRE2_SPTR)tmp, pent->nlen - (tmp - pent->name) - 1, 0, 0, match_data, NULL); + pcre2_match_data_free(match_data); + } else + r = 0; + + if (r > 0) { #else if (tmp && !regexec(&archive_re, tmp, 0, NULL, 0)) { #endif @@ -9005,8 +9016,8 @@ int main(int argc, char *argv[]) /* Set archive handling (enveditor used as tmp var) */ enveditor = getenv(env_cfg[NNN_ARCHIVE]); -#ifdef PCRE - if (setfilter(&archive_pcre, (enveditor ? enveditor : patterns[P_ARCHIVE]))) { +#ifdef PCRE2 + if (setfilter(&archive_pcre2, (enveditor ? enveditor : patterns[P_ARCHIVE]))) { #else if (setfilter(&archive_re, (enveditor ? enveditor : patterns[P_ARCHIVE]))) { #endif @@ -9112,8 +9123,8 @@ int main(int argc, char *argv[]) #ifndef NOLC /* Set locale */ setlocale(LC_ALL, ""); -#ifdef PCRE - tables = pcre_maketables(); +#ifdef PCRE2 + tables = pcre2_maketables(NULL); #endif #endif @@ -9191,8 +9202,8 @@ int main(int argc, char *argv[]) rmlistpath(); /* Free the regex */ -#ifdef PCRE - pcre_free(archive_pcre); +#ifdef PCRE2 + pcre2_code_free(archive_pcre2); #else regfree(&archive_re); #endif