diff options
author | Thomas Voss <mail@thomasvoss.com> | 2024-11-01 21:43:01 +0100 |
---|---|---|
committer | Thomas Voss <mail@thomasvoss.com> | 2024-11-01 21:43:01 +0100 |
commit | 4f41e06880f4d9b979ec001da5046373cd867c2f (patch) | |
tree | f084ed93e8387e3fa814aa17dee80b5a263bf81b | |
parent | 420d354fffa1e69f050ba32d8521c6d84c4f8dd1 (diff) |
Add -H
-rw-r--r-- | src/globals.h | 23 | ||||
-rw-r--r-- | src/main.c | 23 | ||||
-rw-r--r-- | src/work.c | 30 | ||||
m--------- | vendor/mlib | 0 |
4 files changed, 67 insertions, 9 deletions
diff --git a/src/globals.h b/src/globals.h index 1285db3..f0ed91b 100644 --- a/src/globals.h +++ b/src/globals.h @@ -15,15 +15,22 @@ typedef struct { #endif } op_t; +enum { + HDR_NEVER, + HDR_MULTI, + HDR_ALWAYS, +}; + typedef struct { - bool b : 1; - bool c : 1; - bool i : 1; - bool l : 1; - bool p : 1; - bool s : 1; - bool U : 1; - bool z : 1; + bool b : 1; + bool c : 1; + unsigned H : 2; + bool i : 1; + bool l : 1; + bool p : 1; + bool s : 1; + bool U : 1; + bool z : 1; #if !GIT_GRAB bool do_header : 1; @@ -69,6 +69,7 @@ main(int argc, char **argv) {'b', U8C("byte-offset"), CLI_NONE}, {'c', U8C("color"), CLI_NONE}, {'h', U8C("help"), CLI_NONE}, + {'H', U8C("header-line"), CLI_REQ}, {'i', U8C("ignore-case"), CLI_NONE}, {'l', U8C("literal"), CLI_NONE}, {'L', U8C("line-position"), CLI_NONE}, @@ -95,6 +96,26 @@ main(int argc, char **argv) case 'h': execlp("man", "man", "1", mlib_progname(), nullptr); err("execlp: man 1 %s:", mlib_progname()); + case 'H': + if (ucseq(parser.optarg, U8("never"))) + flags.H = HDR_NEVER; + else if (ucseq(parser.optarg, U8("multi"))) + flags.H = HDR_MULTI; + else if (ucseq(parser.optarg, U8("always"))) + flags.H = HDR_ALWAYS; + else if (parser.optarg.len == 0) { + warn("empty value given for option %s--header-line%s", + lquot, rquot); + goto usage; + } else { + warn("unknown value %s%.*s%s for option %s--header-line%s", + lquot, SV_PRI_ARGS(parser.optarg), rquot, lquot, rquot); + goto usage; + } +#if !GIT_GRAB + flags.do_header = true; +#endif + break; case 'i': flags.i = true; break; @@ -130,7 +151,7 @@ main(int argc, char **argv) if (argc == 0) { usage: - usage("[-bcilLpsUz] pattern [file ...]", "-h"); + usage("[-H never|multi|always] [-bcilLpsUz] pattern [file ...]", "-h"); exit(EXIT_FATAL); } @@ -18,6 +18,7 @@ #include <macros.h> #include <mbstring.h> #include <pcre2.h> +#include <rune.h> #include <unicode/string.h> #include "exitcodes.h" @@ -39,6 +40,7 @@ typedef struct { } pos_state_t; static void compute_pos(const char8_t *p, pos_state_t *ps); +static bool has_lbrk_p(u8view_t sv); static bool islbrk(u8view_t g); static int svposcmp(const void *a, const void *b); static void write_match_to_buffer(u8view_t sv, u8view_t *hl); @@ -375,6 +377,15 @@ write_match_to_buffer(u8view_t sv, u8view_t *hl) array_extend_sv(buf, COL_SE); array_push(buf, sep); array_extend_sv(buf, COL_RS); + + switch (flags.H) { + case HDR_ALWAYS: + array_push(buf, '\n'); + break; + case HDR_MULTI: + if (has_lbrk_p(sv)) + array_push(buf, '\n'); + } } #pragma GCC diagnostic pop @@ -453,6 +464,25 @@ compute_pos(const char8_t *p, pos_state_t *ps) } bool +has_lbrk_p(u8view_t sv) +{ + rune ch; + while (ucsnext(&ch, &sv) != 0) { + switch (ch) { + case '\r': /* Not *really* a newline, but it can mess with output */ + case '\n': + case '\v': + case '\f': + case 0x85: + case RUNE_C(0x2028): + case RUNE_C(0x2029): + return true; + } + } + return false; +} + +bool islbrk(u8view_t g) { return ucseq(g, U8("\n")) diff --git a/vendor/mlib b/vendor/mlib -Subproject 045f4bb5b1767140c4f6cfe2d2002553925c420 +Subproject 192cabe89d0baa1b2f32434c830b40e82f5a785 |