help: add "man.viewer" config var to use "woman" or "konqueror"
[gitweb.git] / help.c
diff --git a/help.c b/help.c
index e57a50ed59badbb968ce508b6c1802f1fcb68903..2cb152d2e10cad363c639a8e65f37cbd6fc42d64 100644 (file)
--- a/help.c
+++ b/help.c
@@ -8,6 +8,9 @@
 #include "exec_cmd.h"
 #include "common-cmds.h"
 #include "parse-options.h"
+#include "run-command.h"
+
+static const char *man_viewer;
 
 enum help_format {
        HELP_FORMAT_MAN,
@@ -50,6 +53,8 @@ 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);
        return git_default_config(var, value);
 }
 
@@ -345,11 +350,85 @@ 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)
 {
        const char *page = cmd_to_page(git_cmd);
        setup_man_path();
-       execlp("man", "man", page, NULL);
+       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);
 }
 
 static void show_info_page(const char *git_cmd)