git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jeff King <peff@peff.net>
To: Junio C Hamano <gitster@pobox.com>
Cc: Kevin Ballard <kevin@sb.org>, Git Mailing List <git@vger.kernel.org>
Subject: Re: To page or not to page
Date: Tue, 6 May 2008 01:51:28 -0400	[thread overview]
Message-ID: <20080506055128.GA26311@sigill.intra.peff.net> (raw)
In-Reply-To: <7v1w4ky3hh.fsf@gitster.siamese.dyndns.org>

On Fri, May 02, 2008 at 11:18:02AM -0700, Junio C Hamano wrote:

> Hmm. How about doing things this way?
> 
>  - at the beginning of handle_options() remember argv[0]
> 
>  - restructure handle_options() so that it does not run setup_pager() and
>    setenv("GIT_PAGER", "cat", 1) inside the loop, but instead remember
>    what we had on the command line;
> 
>  - after the handle_options() loop, if we saw an explicit --pager,
>    --no-pager, that's the decision;

This is actually a bit tricky, since there are two code paths; builtins
called as git-foo never even go to handle_options, but they can still
look up the config value.

So how about this:

 - keep a global use_pager = { 0 (explicit no), 1 (explicit yes), -1
   (unknown) }

 - if git-foo, lookup config for pager.foo

 - otherwise we have "git [options] foo"; look for -p / --no-pager; if
   none found, then lookup config for "foo"

 - before proceeding further, "commit" the pager choice by running it
   (if 1), munging GIT_PAGER=cat (if 0), or doing nothing (if -1)

 - before handling an internal command, if use_pager is -1 and the
   command defaults to a pager, we run it then

The patch below implements this.

It would be nice to actually defer running the pager until we are about
to run a git command. I.e., never "commit" to the pager until we are
actually running an internal command or exec'ing an external command.
That way it would be safe to make an alias that called "--no-pager"
(which is currently disallowed).

That works for internal commands, since we know we are going to run one,
and if it fails, we die.  However, for external commands, we just exec
and hope it works. So if we run the pager beforehand, we are now
committed to it, and a further alias cannot set --no-pager. We could
alternatively run it after deciding that running the command is what
we'll do, but then we have to do the PATH lookup ourselves.

So anyway, here is the less invasive version.

---
 git.c |   48 ++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 44 insertions(+), 4 deletions(-)

diff --git a/git.c b/git.c
index 89b431f..dadca41 100644
--- a/git.c
+++ b/git.c
@@ -6,12 +6,46 @@
 const char git_usage_string[] =
 	"git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
 
+static int use_pager = -1;
+static const char *pager_command_key;
+static int pager_command_value;
+
+int pager_command_config(const char *var, const char *value)
+{
+	if (!prefixcmp(var, "pager.") && !strcmp(var + 6, pager_command_key))
+		pager_command_value = git_config_bool(var, value);
+	return 0;
+}
+
+/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
+int check_pager_config(const char *cmd)
+{
+	pager_command_key = cmd;
+	pager_command_value = -1;
+	git_config(pager_command_config);
+	return pager_command_value;
+}
+
+static void commit_pager_choice(void) {
+	switch (use_pager) {
+	case 0:
+		setenv("GIT_PAGER", "cat", 1);
+		break;
+	case 1:
+		setup_pager();
+		break;
+	default:
+		break;
+	}
+}
+
 static int handle_options(const char*** argv, int* argc, int* envchanged)
 {
 	int handled = 0;
+	const char *cmd = NULL;
 
 	while (*argc > 0) {
-		const char *cmd = (*argv)[0];
+		cmd = (*argv)[0];
 		if (cmd[0] != '-')
 			break;
 
@@ -35,9 +69,9 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
 				exit(0);
 			}
 		} else if (!strcmp(cmd, "-p") || !strcmp(cmd, "--paginate")) {
-			setup_pager();
+			use_pager = 1;
 		} else if (!strcmp(cmd, "--no-pager")) {
-			setenv("GIT_PAGER", "cat", 1);
+			use_pager = 0;
 			if (envchanged)
 				*envchanged = 1;
 		} else if (!strcmp(cmd, "--git-dir")) {
@@ -84,6 +118,9 @@ static int handle_options(const char*** argv, int* argc, int* envchanged)
 		(*argc)--;
 		handled++;
 	}
+
+	if (use_pager == -1 && cmd)
+		use_pager = check_pager_config(cmd);
 	return handled;
 }
 
@@ -239,7 +276,7 @@ static int run_command(struct cmd_struct *p, int argc, const char **argv)
 	prefix = NULL;
 	if (p->option & RUN_SETUP)
 		prefix = setup_git_directory();
-	if (p->option & USE_PAGER)
+	if (use_pager == -1 && p->option & USE_PAGER)
 		setup_pager();
 	if (p->option & NEED_WORK_TREE)
 		setup_work_tree();
@@ -411,6 +448,8 @@ int main(int argc, const char **argv)
 	if (!prefixcmp(cmd, "git-")) {
 		cmd += 4;
 		argv[0] = cmd;
+		use_pager = check_pager_config(cmd);
+		commit_pager_choice();
 		handle_internal_command(argc, argv);
 		die("cannot handle %s internally", cmd);
 	}
@@ -419,6 +458,7 @@ int main(int argc, const char **argv)
 	argv++;
 	argc--;
 	handle_options(&argv, &argc, NULL);
+	commit_pager_choice();
 	if (argc > 0) {
 		if (!prefixcmp(argv[0], "--"))
 			argv[0] += 2;
-- 
1.5.5.1.244.g148a.dirty

  parent reply	other threads:[~2008-05-06  5:52 UTC|newest]

Thread overview: 31+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-05-02  5:41 To page or not to page Kevin Ballard
2008-05-02  5:45 ` Jeff King
2008-05-02  5:56   ` Junio C Hamano
2008-05-02  6:04     ` Kevin Ballard
2008-05-02  6:08       ` Junio C Hamano
2008-05-02 13:47         ` Bart Trojanowski
2008-05-02  9:41       ` Pedro Melo
2008-05-02 16:58         ` Kevin Ballard
2008-05-02 10:34       ` Wincent Colaiuta
2008-05-02 12:36         ` Jeff King
2008-05-02 13:49           ` Pedro Melo
2008-05-02 14:00           ` Aidan Van Dyk
2008-05-02 16:13           ` Wincent Colaiuta
2008-05-02 16:56             ` Kevin Ballard
2008-05-02 18:40               ` Wincent Colaiuta
2008-05-02  6:11     ` Jeff King
2008-05-02  7:53       ` Johannes Schindelin
2008-05-02  6:09   ` Jeff King
2008-05-02  6:19     ` Junio C Hamano
2008-05-02 12:55       ` Jeff King
2008-05-02 18:18         ` Junio C Hamano
2008-05-05 21:59           ` Jeff King
2008-05-06  5:51           ` Jeff King [this message]
2008-05-06  5:53             ` Jeff King
2008-05-11 17:15             ` Junio C Hamano
2008-05-16  4:42             ` Jeff King
2008-05-16  4:51               ` Jeff King
2008-05-16 10:29                 ` Johannes Schindelin
2008-05-02  6:56     ` Jakub Narebski
2008-05-02 12:57       ` Jeff King
2008-05-02 15:36     ` Jeff King

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20080506055128.GA26311@sigill.intra.peff.net \
    --to=peff@peff.net \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=kevin@sb.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).