git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] grep -A/-B/-Cinfinity to get full context

From
Jonathan Nieder <jrnieder@gmail.com>
Date
Aug 20, 2010, 11:55 UTC
Message-ID
<20100820115527.GR10407@burratino>
In-Reply-To
<201008201122.09392.jnareb@gmail.com>
Just a proof of concept.
Cc: René Scharfe <rene.scharfe@lsrfire.ath.cx>
Signed-off-by: Jonathan Nieder <jrnieder@gmail.com>
---
Jakub Narebski wrote:
> If there were more options that use <n> == 0 to actually mean unlimited
> (infinity), perhaps it would be better to extend parseopt to provide for
> such situation, e.g. OPT_INT_INF or something.
Something like this, maybe.
 Documentation/technical/api-parse-options.txt |    6 ++++++
 builtin/grep.c                                |    8 ++++++--
 grep.c                                        |    8 +++++---
 grep.h                                        |    4 ++--
 parse-options.c                               |   21 +++++++++++++++++++++
 parse-options.h                               |    4 ++++
 6 files changed, 44 insertions(+), 7 deletions(-)
diff --git a/Documentation/technical/api-parse-options.txt b/Documentation/technical/api-parse-options.txt
index 312e3b2..f152a3f 100644
--- a/Documentation/technical/api-parse-options.txt
+++ b/Documentation/technical/api-parse-options.txt
@@ -160,6 +160,12 @@ There are some macros to easily define options:
 	Introduce an option with integer argument.
 	The integer is put into `int_var`.
 
+`OPT_INT_INF(short, long, &int_var, inf_val, description)`::
+	Introduce an option with integer argument.
+	The integer is put into `int_var`.  If the special value
+	"inf" (or "infinity") is used as an argument, then `inf_val`
+	is put into `int_var`.
+
 `OPT_DATE(short, long, &int_var, description)`::
 	Introduce an option with date argument, see `approxidate()`.
 	The timestamp is put into `int_var`.
diff --git a/builtin/grep.c b/builtin/grep.c
index 597f76b..9fbc985 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -750,6 +750,10 @@ static int context_callback(const struct option *opt, const char *arg,
 		grep_opt->pre_context = grep_opt->post_context = 0;
 		return 0;
 	}
+	if (!strcasecmp(arg, "inf") || !strcasecmp(arg, "infinity")) {
+		grep_opt->pre_context = grep_opt->post_context = -1;
+		return 0;
+	}
 	value = strtol(arg, (char **)&endp, 10);
 	if (*endp) {
 		return error("switch `%c' expects a numerical value",
@@ -890,9 +894,9 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
 		OPT_CALLBACK('C', NULL, &opt, "n",
 			"show <n> context lines before and after matches",
 			context_callback),
-		OPT_INTEGER('B', NULL, &opt.pre_context,
+		OPT_INT_INF('B', NULL, &opt.pre_context, -1,
 			"show <n> context lines before matches"),
-		OPT_INTEGER('A', NULL, &opt.post_context,
+		OPT_INT_INF('A', NULL, &opt.post_context, -1,
 			"show <n> context lines after matches"),
 		OPT_NUMBER_CALLBACK(&opt, "shortcut for -C NUM",
 			context_callback),
diff --git a/grep.c b/grep.c
index 82fb349..793d41f 100644
--- a/grep.c
+++ b/grep.c
@@ -687,7 +687,7 @@ static void show_pre_context(struct grep_opt *opt, const char *name, char *buf,
 	unsigned cur = lno, from = 1, funcname_lno = 0;
 	int funcname_needed = opt->funcname;
 
-	if (opt->pre_context < lno)
+	if (opt->pre_context >= 0 && opt->pre_context < lno)
 		from = lno - opt->pre_context;
 	if (from <= opt->last_shown)
 		from = opt->last_shown + 1;
@@ -861,7 +861,8 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
 		 */
 		if (try_lookahead
 		    && !(last_hit
-			 && lno <= last_hit + opt->post_context)
+			 && (opt->post_context < 0
+			     || lno <= last_hit + opt->post_context))
 		    && look_ahead(opt, &left, &lno, &bol))
 			break;
 		eol = end_of_line(bol, &left);
@@ -916,7 +917,8 @@ static int grep_buffer_1(struct grep_opt *opt, const char *name,
 			last_hit = lno;
 		}
 		else if (last_hit &&
-			 lno <= last_hit + opt->post_context) {
+			 (opt->post_context < 0 ||
+			  lno <= last_hit + opt->post_context)) {
 			/* If the last hit is within the post context,
 			 * we need to show this line.
 			 */
diff --git a/grep.h b/grep.h
index efa8cff..13aae94 100644
--- a/grep.h
+++ b/grep.h
@@ -95,8 +95,8 @@ struct grep_opt {
 	char color_selected[COLOR_MAXLEN];
 	char color_sep[COLOR_MAXLEN];
 	int regflags;
-	unsigned pre_context;
-	unsigned post_context;
+	int pre_context;
+	int post_context;
 	unsigned last_shown;
 	int show_hunk_mark;
 	void *priv;
diff --git a/parse-options.c b/parse-options.c
index 0fa79bc..b299125 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -612,6 +612,27 @@ int parse_opt_approxidate_cb(const struct option *opt, const char *arg,
 	return 0;
 }
 
+int parse_opt_infinity_cb(const struct option *opt, const char *arg,
+			  int unset)
+{
+	const char *endp;
+
+	if (unset) {
+		*(int *)opt->value = 0;
+		return 0;
+	}
+	if (!arg)
+		return opterror(opt, "expects a numerical value", 0);
+	if (!strcasecmp(arg, "inf") || !strcasecmp(arg, "infinity")) {
+		*(int *)opt->value = opt->defval;
+		return 0;
+	}
+	*(int *)opt->value = strtol(arg, (char **)&endp, 10);
+	if (*endp)
+		return opterror(opt, "expects a numerical value", 0);
+	return 0;
+}
+
 int parse_opt_color_flag_cb(const struct option *opt, const char *arg,
 			    int unset)
 {
diff --git a/parse-options.h b/parse-options.h
index 7435cdb..6ae041a 100644
--- a/parse-options.h
+++ b/parse-options.h
@@ -126,6 +126,9 @@ struct option {
 #define OPT_STRING(s, l, v, a, h)   { OPTION_STRING,  (s), (l), (v), (a), (h) }
 #define OPT_UYN(s, l, v, h)         { OPTION_CALLBACK, (s), (l), (v), NULL, \
 				      (h), PARSE_OPT_NOARG, &parse_opt_tertiary }
+#define OPT_INT_INF(s, l, v, i, h) \
+	{ OPTION_CALLBACK, (s), (l), (v), "n", (h), 0, \
+	  parse_opt_infinity_cb, (intptr_t)(i) }
 #define OPT_DATE(s, l, v, h) \
 	{ OPTION_CALLBACK, (s), (l), (v), "time",(h), 0, \
 	  parse_opt_approxidate_cb }
@@ -193,6 +196,7 @@ extern int parse_options_concat(struct option *dst, size_t, struct option *src);
 /*----- some often used options -----*/
 extern int parse_opt_abbrev_cb(const struct option *, const char *, int);
 extern int parse_opt_approxidate_cb(const struct option *, const char *, int);
+extern int parse_opt_infinity_cb(const struct option *, const char *, int);
 extern int parse_opt_color_flag_cb(const struct option *, const char *, int);
 extern int parse_opt_verbosity_cb(const struct option *, const char *, int);
 extern int parse_opt_with_commit(const struct option *, const char *, int);
-- 
1.7.2.2.536.g42dab.dirty
Previous: Ramkumar RamachandraNext: Ramkumar Ramachandra
Message 14 of 16 in “fully deepening a shallow clone”
  1. Joey HessAug 17, 2010
  2. Nguyen Thai Ngoc DuyAug 18, 2010
  3. Daniel JohnsonAug 18, 2010
  4. 1/3 clone: do not accept --depth on local clonesNguyễn Thái Ngọc Duy, Aug 19, 2010
  5. Daniel JohnsonAug 19, 2010
  6. Nguyen Thai Ngoc DuyAug 19, 2010
  7. Mikael MagnussonAug 19, 2010
  8. 2/3 fetch-pack: use args.shallow to detect shallow clone instead of args.depthNguyễn Thái Ngọc Duy, Aug 19, 2010
  9. 3/3 {fetch,upload}-pack: allow --depth=0 to deepen into full repo againNguyễn Thái Ngọc Duy, Aug 19, 2010
  10. Jakub NarebskiAug 19, 2010
  11. Nguyen Thai Ngoc DuyAug 19, 2010
  12. Jakub NarebskiAug 20, 2010
  13. Ramkumar RamachandraAug 20, 2010
  14. grep -A/-B/-Cinfinity to get full contextJonathan Nieder, Aug 20, 2010
  15. Ramkumar RamachandraAug 20, 2010
  16. Joey HessAug 18, 2010

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.