diff options
| -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 |