Re: [PATCH 2/3] help.c: make term_columns() cached and export it

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 02/11/2012 05:36 AM, Nguyen Thai Ngoc Duy wrote:
2012/2/10 Zbigniew Jędrzejewski-Szmek<zbyszek@xxxxxxxxx>:
Since term_columns() will usually fail, when a pager is installed,
the cache is primed before the pager is installed. If a pager is not
installed, then the cache will be set on first use.

Conflict alert. term_columns() is also moved out of help.c in
nd/columns series on pu, commit cb0850f (Save terminal width before
setting up pager - 2012-02-04)

Thanks for the heads-up. I think that the two patches should be
merged, especially because there's an error in cb0850f (a variable is
read-only, never written).

Tweaks to cb0850f (Save terminal width before setting up pager - 2012-02-04):

[This actually was done on top of today's pu, so it will not apply
 cleanly to cb0850f].

- term_columns() lives in pager.c so it should be declared in
  cache.h like other public functions in pager.c. It has nothing to do
  with columns.h.
- simplify logic to use a static variable instead of two global
  variables (cb0850f actually doesn't work at all because
  spawned_pager wasn't ever set).
- check the cache first, then do getenv(COLUMNS) + atoi, then do
  ioctl(). The behaviour is equivalent to checking COLUMNS first, but
  is slightly more efficient.
- document the function
- remove #include "column.h" added in 88c9754c4097 column: Fix some
  compiler and sparse warnings (Wed Feb 8 2012).

Junio suggested that "a new file, term.c or something, be a lot more
suitable home for the function you will be reusing from diff and other
parts of the system". Nevertheless, I think that adding two files (.c
and .h) to hold one function isn't worth it. It can live in pager.c.
Terminal size is logically connected to paging after all.
---
 cache.h  |    1 +
 column.h |    1 -
 pager.c  |   64 +++++++++++++++++++++++-----------------
 3 files changed, 38 insertions(+), 28 deletions(-)

diff --git a/cache.h b/cache.h
index 6c70dbc..b4422d4 100644
--- a/cache.h
+++ b/cache.h
@@ -1196,6 +1196,7 @@ extern void setup_pager(void);
 extern const char *pager_program;
 extern int pager_in_use(void);
 extern int pager_use_color;
+extern int term_columns(void);

 extern const char *editor_program;
 extern const char *askpass_program;
diff --git a/column.h b/column.h
index b9dec64..142299e 100644
--- a/column.h
+++ b/column.h
@@ -17,7 +17,6 @@ struct column_options {
 	const char *nl;
 };

-extern int term_columns(void);
 extern void print_columns(const struct string_list *list,
 			  unsigned int mode,
 			  struct column_options *opts);
diff --git a/pager.c b/pager.c
index fe203a7..d105761 100644
--- a/pager.c
+++ b/pager.c
@@ -7,21 +7,6 @@
 #define DEFAULT_PAGER "less"
 #endif

-static int spawned_pager;
-static int max_columns;
-
-static int retrieve_terminal_width(void)
-{
-#ifdef TIOCGWINSZ
-	struct winsize ws;
-	if (ioctl(1, TIOCGWINSZ, &ws))  /* e.g., ENOSYS */
-		return 0;
-	return ws.ws_col;
-#else
-	return 0;
-#endif
-}
-
 /*
  * This is split up from the rest of git so that we can do
  * something different on Windows.
@@ -88,16 +73,15 @@ const char *git_pager(int stdout_is_tty)
 void setup_pager(void)
 {
 	const char *pager = git_pager(isatty(1));
-	int width;

 	if (!pager || pager_in_use())
 		return;

-	setenv("GIT_PAGER_IN_USE", "true", 1);
+	/* prime the term_columns() cache before it is too
+	 * late and stdout is replaced */
+	(void) term_columns();

-	width = retrieve_terminal_width();
-	if (width)
-		max_columns = width;
+	setenv("GIT_PAGER_IN_USE", "true", 1);

 	/* spawn the pager */
 	pager_argv[0] = pager;
@@ -132,17 +116,43 @@ int pager_in_use(void)
 	return env ? git_config_bool("GIT_PAGER_IN_USE", env) : 0;
 }

+/*
+ * Return cached value (if set) or $COLUMNS (if set and positive) or
+ * ioctl(1, TIOCGWINSZ).ws_col (if positive) or 80.
+ *
+ * $COLUMNS even if set, is usually not exported, so
+ * the variable can be used to override autodection.
+ * This behaviour conforms to The Single UNIX Specification, Version 2
+ * (http://pubs.opengroup.org/onlinepubs/7908799/xbd/envvar.html#tag_002_003).
+ */
 int term_columns(void)
 {
-	char *col_string = getenv("COLUMNS");
+	static int term_columns_cache;
+
+	char *col_string;
 	int n_cols;

-	if (col_string && (n_cols = atoi(col_string)) > 0)
-		return n_cols;
+	if (term_columns_cache)
+		return term_columns_cache;
+
+	col_string = getenv("COLUMNS");
+	if (col_string && (n_cols = atoi(col_string)) > 0) {
+		term_columns_cache = n_cols;
+		return term_columns_cache;
+	}

-	if (spawned_pager && max_columns)
-		return max_columns;
+#ifdef TIOCGWINSZ
+	{
+		struct winsize ws;
+		if (!ioctl(1, TIOCGWINSZ, &ws)) {
+			if (ws.ws_col) {
+				term_columns_cache = ws.ws_col;
+				return term_columns_cache;
+			}
+		}
+	}
+#endif

-	n_cols = retrieve_terminal_width();
-	return n_cols ? n_cols : 80;
+	term_columns_cache = 80;
+	return term_columns_cache;
 }
--
1.7.9.310.g883d84c.dirty

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]