summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Couder <chriscool@tuxfamily.org>2008-03-11 07:51:12 (GMT)
committerJunio C Hamano <gitster@pobox.com>2008-03-12 06:02:01 (GMT)
commit69099d6bedb0217d7c35f7202acd6185551d762f (patch)
tree40438d02669845d87eff74462931e38837d929f1
parentb5578f333595e40cb843461e685c887ad2d01e5c (diff)
downloadgit-69099d6bedb0217d7c35f7202acd6185551d762f.zip
git-69099d6bedb0217d7c35f7202acd6185551d762f.tar.gz
git-69099d6bedb0217d7c35f7202acd6185551d762f.tar.bz2
help: implement multi-valued "man.viewer" config option
This allows multiple viewer candidates to be listed in the configuration file, like this: [man] viewer = woman viewer = konqueror viewer = man The candidates are tried in the order listed in the configuration file, and the first suitable one (e.g. konqueror cannot be used outside windowed environment) is used. Signed-off-by: Christian Couder <chriscool@tuxfamily.org> Tested-by: Xavier Maillard <xma@gnu.org> Signed-off-by: Junio C Hamano <gitster@pobox.com>
-rw-r--r--help.c191
1 files changed, 113 insertions, 78 deletions
diff --git a/help.c b/help.c
index 2cb152d..5da8c9c 100644
--- a/help.c
+++ b/help.c
@@ -10,7 +10,10 @@
#include "parse-options.h"
#include "run-command.h"
-static const char *man_viewer;
+static struct man_viewer_list {
+ void (*exec)(const char *);
+ struct man_viewer_list *next;
+} *man_viewer_list;
enum help_format {
HELP_FORMAT_MAN,
@@ -45,6 +48,102 @@ static enum help_format parse_help_format(const char *format)
die("unrecognized help format '%s'", format);
}
+static int check_emacsclient_version(void)
+{
+ struct strbuf buffer = STRBUF_INIT;
+ struct child_process ec_process;
+ const char *argv_ec[] = { "emacsclient", "--version", NULL };
+ int version;
+
+ /* emacsclient prints its version number on stderr */
+ memset(&ec_process, 0, sizeof(ec_process));
+ ec_process.argv = argv_ec;
+ ec_process.err = -1;
+ ec_process.stdout_to_stderr = 1;
+ if (start_command(&ec_process)) {
+ fprintf(stderr, "Failed to start emacsclient.\n");
+ return -1;
+ }
+ strbuf_read(&buffer, ec_process.err, 20);
+ close(ec_process.err);
+
+ /*
+ * Don't bother checking return value, because "emacsclient --version"
+ * seems to always exits with code 1.
+ */
+ finish_command(&ec_process);
+
+ if (prefixcmp(buffer.buf, "emacsclient")) {
+ fprintf(stderr, "Failed to parse emacsclient version.\n");
+ strbuf_release(&buffer);
+ return -1;
+ }
+
+ strbuf_remove(&buffer, 0, strlen("emacsclient"));
+ version = atoi(buffer.buf);
+
+ if (version < 22) {
+ fprintf(stderr,
+ "emacsclient version '%d' too old (< 22).\n",
+ version);
+ strbuf_release(&buffer);
+ return -1;
+ }
+
+ strbuf_release(&buffer);
+ return 0;
+}
+
+static void exec_woman_emacs(const char *page)
+{
+ if (!check_emacsclient_version()) {
+ /* This works only with emacsclient version >= 22. */
+ struct strbuf man_page = STRBUF_INIT;
+ strbuf_addf(&man_page, "(woman \"%s\")", page);
+ execlp("emacsclient", "emacsclient", "-e", man_page.buf, NULL);
+ }
+}
+
+static void exec_man_konqueror(const char *page)
+{
+ const char *display = getenv("DISPLAY");
+ if (display && *display) {
+ struct strbuf man_page = STRBUF_INIT;
+ strbuf_addf(&man_page, "man:%s(1)", page);
+ execlp("kfmclient", "kfmclient", "newTab", man_page.buf, NULL);
+ }
+}
+
+static void exec_man_man(const char *page)
+{
+ execlp("man", "man", page, NULL);
+}
+
+static void do_add_man_viewer(void (*exec)(const char *))
+{
+ struct man_viewer_list **p = &man_viewer_list;
+
+ while (*p)
+ p = &((*p)->next);
+ *p = xmalloc(sizeof(**p));
+ (*p)->next = NULL;
+ (*p)->exec = exec;
+}
+
+static int add_man_viewer(const char *value)
+{
+ if (!strcasecmp(value, "man"))
+ do_add_man_viewer(exec_man_man);
+ else if (!strcasecmp(value, "woman"))
+ do_add_man_viewer(exec_woman_emacs);
+ else if (!strcasecmp(value, "konqueror"))
+ do_add_man_viewer(exec_man_konqueror);
+ else
+ return error("'%s': unsupported man viewer.", value);
+
+ return 0;
+}
+
static int git_help_config(const char *var, const char *value)
{
if (!strcmp(var, "help.format")) {
@@ -53,8 +152,11 @@ static int git_help_config(const char *var, const char *value)
help_format = parse_help_format(value);
return 0;
}
- if (!strcmp(var, "man.viewer"))
- return git_config_string(&man_viewer, var, value);
+ if (!strcmp(var, "man.viewer")) {
+ if (!value)
+ return config_error_nonbool(var);
+ return add_man_viewer(value);
+ }
return git_default_config(var, value);
}
@@ -350,85 +452,18 @@ static void setup_man_path(void)
strbuf_release(&new_path);
}
-static int check_emacsclient_version(void)
-{
- struct strbuf buffer = STRBUF_INIT;
- struct child_process ec_process;
- const char *argv_ec[] = { "emacsclient", "--version", NULL };
- int version;
-
- /* emacsclient prints its version number on stderr */
- memset(&ec_process, 0, sizeof(ec_process));
- ec_process.argv = argv_ec;
- ec_process.err = -1;
- ec_process.stdout_to_stderr = 1;
- if (start_command(&ec_process)) {
- fprintf(stderr, "Failed to start emacsclient.\n");
- return -1;
- }
- strbuf_read(&buffer, ec_process.err, 20);
- close(ec_process.err);
-
- /*
- * Don't bother checking return value, because "emacsclient --version"
- * seems to always exits with code 1.
- */
- finish_command(&ec_process);
-
- if (prefixcmp(buffer.buf, "emacsclient")) {
- fprintf(stderr, "Failed to parse emacsclient version.\n");
- strbuf_release(&buffer);
- return -1;
- }
-
- strbuf_remove(&buffer, 0, strlen("emacsclient"));
- version = atoi(buffer.buf);
-
- if (version < 22) {
- fprintf(stderr,
- "emacsclient version '%d' too old (< 22).\n",
- version);
- strbuf_release(&buffer);
- return -1;
- }
-
- strbuf_release(&buffer);
- return 0;
-}
-
-static void exec_woman_emacs(const char *page)
-{
- if (!check_emacsclient_version()) {
- /* This works only with emacsclient version >= 22. */
- struct strbuf man_page = STRBUF_INIT;
- strbuf_addf(&man_page, "(woman \"%s\")", page);
- execlp("emacsclient", "emacsclient", "-e", man_page.buf, NULL);
- } else
- execlp("man", "man", page, NULL);
-}
-
-static void exec_man_konqueror(const char *page)
-{
- const char *display = getenv("DISPLAY");
- if (display && *display) {
- struct strbuf man_page = STRBUF_INIT;
- strbuf_addf(&man_page, "man:%s(1)", page);
- execlp("kfmclient", "kfmclient", "newTab", man_page.buf, NULL);
- } else
- execlp("man", "man", page, NULL);
-}
-
static void show_man_page(const char *git_cmd)
{
+ struct man_viewer_list *viewer;
const char *page = cmd_to_page(git_cmd);
+
setup_man_path();
- if (!man_viewer || !strcmp(man_viewer, "man"))
- execlp("man", "man", page, NULL);
- if (!strcmp(man_viewer, "woman"))
- exec_woman_emacs(page);
- if (!strcmp(man_viewer, "konqueror"))
- exec_man_konqueror(page);
- die("'%s': unsupported man viewer.", man_viewer);
+ for (viewer = man_viewer_list; viewer; viewer = viewer->next)
+ {
+ viewer->exec(page); /* will return when unable */
+ }
+ exec_man_man(page);
+ die("no man viewer handled the request");
}
static void show_info_page(const char *git_cmd)