From 649499845c274dc15809fe3c9162408c334fec57 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Fri, 7 Mar 2008 08:46:28 +0100 Subject: help: add "man.viewer" config var to use "woman" or "konqueror" This patch makes it possible to view man pages using other tools than the "man" program. It also implements support for emacs' "woman" and konqueror with the man KIO slave to view man pages. Note that "emacsclient" is used with option "-e" to launch "woman" on emacs and this works only on versions >= 22. Signed-off-by: Christian Couder Tested-by: Xavier Maillard Signed-off-by: Junio C Hamano diff --git a/help.c b/help.c index e57a50e..2cb152d 100644 --- 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) -- cgit v0.10.2-6-g49f6 From b5578f333595e40cb843461e685c887ad2d01e5c Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Fri, 7 Mar 2008 08:46:55 +0100 Subject: Documentation: help: describe 'man.viewer' config variable Signed-off-by: Christian Couder Tested-by: Xavier Maillard Signed-off-by: Junio C Hamano diff --git a/Documentation/config.txt b/Documentation/config.txt index c5e094a..d2f2d67 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -748,6 +748,10 @@ log.showroot:: Tools like linkgit:git-log[1] or linkgit:git-whatchanged[1], which normally hide the root commit will now show it. True by default. +man.viewer:: + Specify the program that will be used to display help in the + 'man' format. See linkgit:git-help[1]. + merge.summary:: Whether to include summaries of merged commits in newly created merge commit messages. False by default. diff --git a/Documentation/git-help.txt b/Documentation/git-help.txt index 0926dc1..73a51ae 100644 --- a/Documentation/git-help.txt +++ b/Documentation/git-help.txt @@ -33,17 +33,21 @@ OPTIONS option supersedes any other option. -i|--info:: - Use the 'info' program to display the manual page, instead of - the 'man' program that is used by default. + Display manual page for the command in the 'info' format. The + 'info' program will be used for that purpose. -m|--man:: - Use the 'man' program to display the manual page. This may be - used to override a value set in the 'help.format' - configuration variable. + Display manual page for the command in the 'man' format. This + option may be used to override a value set in the + 'help.format' configuration variable. ++ +By default the 'man' program will be used to display the manual page, +but the 'man.viewer' configuration variable may be used to choose +another display program (see below). -w|--web:: - Use a web browser to display the HTML manual page, instead of - the 'man' program that is used by default. + Display manual page for the command in the 'web' (HTML) + format. A web browser will be used for that purpose. + The web browser can be specified using the configuration variable 'help.browser', or 'web.browser' if the former is not set. If none of @@ -61,15 +65,23 @@ line option: * "man" corresponds to '-m|--man', * "info" corresponds to '-i|--info', -* "web" or "html" correspond to '-w|--web', +* "web" or "html" correspond to '-w|--web'. The 'help.browser', 'web.browser' and 'browser..path' will also be checked if the 'web' format is chosen (either by command line option or configuration variable). See '-w|--web' in the OPTIONS section above and linkgit:git-web--browse[1]. -Note that these configuration variables should probably be set using -the '--global' flag, for example like this: +The 'man.viewer' config variable will be checked if the 'man' format +is chosen. Only the following values are currently supported: + +* "man": use the 'man' program as usual, +* "woman": use 'emacsclient' to launch the "woman" mode in emacs +(this only works starting with emacsclient versions 22), +* "konqueror": use a man KIO slave in konqueror. + +Note that all these configuration variables should probably be set +using the '--global' flag, for example like this: ------------------------------------------------ $ git config --global help.format web -- cgit v0.10.2-6-g49f6 From 69099d6bedb0217d7c35f7202acd6185551d762f Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Tue, 11 Mar 2008 08:51:12 +0100 Subject: 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 Tested-by: Xavier Maillard Signed-off-by: Junio C Hamano 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) -- cgit v0.10.2-6-g49f6 From b8322ea83bc23499a2cef883d051859eb79fef25 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Thu, 13 Mar 2008 06:48:46 +0100 Subject: Documentation: help: explain 'man.viewer' multiple values Also add titles to paragraphs under "CONFIGURATION VARIABLES". Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano diff --git a/Documentation/config.txt b/Documentation/config.txt index d2f2d67..ae1486d 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -749,7 +749,7 @@ log.showroot:: normally hide the root commit will now show it. True by default. man.viewer:: - Specify the program that will be used to display help in the + Specify the programs that may be used to display help in the 'man' format. See linkgit:git-help[1]. merge.summary:: diff --git a/Documentation/git-help.txt b/Documentation/git-help.txt index 73a51ae..0354ac9 100644 --- a/Documentation/git-help.txt +++ b/Documentation/git-help.txt @@ -43,7 +43,7 @@ OPTIONS + By default the 'man' program will be used to display the manual page, but the 'man.viewer' configuration variable may be used to choose -another display program (see below). +other display programs (see below). -w|--web:: Display manual page for the command in the 'web' (HTML) @@ -58,6 +58,9 @@ linkgit:git-web--browse[1] for more information about this. CONFIGURATION VARIABLES ----------------------- +help.format +~~~~~~~~~~~ + If no command line option is passed, the 'help.format' configuration variable will be checked. The following values are supported for this variable; they make 'git-help' behave as their corresponding command @@ -67,11 +70,17 @@ line option: * "info" corresponds to '-i|--info', * "web" or "html" correspond to '-w|--web'. +help.browser, web.browser and browser..path +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + The 'help.browser', 'web.browser' and 'browser..path' will also be checked if the 'web' format is chosen (either by command line option or configuration variable). See '-w|--web' in the OPTIONS section above and linkgit:git-web--browse[1]. +man.viewer +~~~~~~~~~~ + The 'man.viewer' config variable will be checked if the 'man' format is chosen. Only the following values are currently supported: @@ -80,6 +89,24 @@ is chosen. Only the following values are currently supported: (this only works starting with emacsclient versions 22), * "konqueror": use a man KIO slave in konqueror. +Multiple values may be given to this configuration variable. Their +corresponding programs will be tried in the order listed in the +configuration file. + +For example, this configuration: + + [man] + viewer = konqueror + viewer = woman + +will try to use konqueror first. But this may fail (for example if +DISPLAY is not set) and in that case emacs' woman mode will be tried. + +If everythings fails the 'man' program will be tried anyway. + +Note about git config --global +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Note that all these configuration variables should probably be set using the '--global' flag, for example like this: -- cgit v0.10.2-6-g49f6 From 5fb0b3e007d6465af99d08121d46be82c649df5a Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Thu, 13 Mar 2008 07:10:40 +0100 Subject: help: warn if specified 'man.viewer' is unsupported, instead of erroring out When a document viewer that is unknown to the current version of git is specified in the .git/config file, instead of erroring out the process entirely, just issue a warning. It might be that the user usually is using a newer git that supports it (and the configuration is written for that version) but is temporarily using an older git that does not know the viewer. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano diff --git a/help.c b/help.c index 5da8c9c..ecaca77 100644 --- a/help.c +++ b/help.c @@ -139,7 +139,7 @@ static int add_man_viewer(const char *value) else if (!strcasecmp(value, "konqueror")) do_add_man_viewer(exec_man_konqueror); else - return error("'%s': unsupported man viewer.", value); + warning("'%s': unsupported man viewer.", value); return 0; } -- cgit v0.10.2-6-g49f6 From 63f671a4406f33bf689d854596124a40f5b9a22a Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 13 Mar 2008 19:15:30 -0700 Subject: Documentation/git-help: typofix Noticed by Xavier Maillard Signed-off-by: Junio C Hamano diff --git a/Documentation/git-help.txt b/Documentation/git-help.txt index 0354ac9..be2ae53 100644 --- a/Documentation/git-help.txt +++ b/Documentation/git-help.txt @@ -102,7 +102,7 @@ For example, this configuration: will try to use konqueror first. But this may fail (for example if DISPLAY is not set) and in that case emacs' woman mode will be tried. -If everythings fails the 'man' program will be tried anyway. +If everything fails the 'man' program will be tried anyway. Note about git config --global ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- cgit v0.10.2-6-g49f6