diff options
-rw-r--r-- | Documentation/config.txt | 4 | ||||
-rw-r--r-- | Documentation/git-help.txt | 59 | ||||
-rw-r--r-- | help.c | 116 |
3 files changed, 168 insertions, 11 deletions
diff --git a/Documentation/config.txt b/Documentation/config.txt index ed2cb832b..0865f4e01 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -757,6 +757,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 programs that may 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 0926dc12b..be2ae53b9 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 +other display programs (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 @@ -54,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 @@ -61,15 +68,47 @@ 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'. + +help.browser, web.browser and browser.<tool>.path +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ The 'help.browser', 'web.browser' and 'browser.<tool>.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: +man.viewer +~~~~~~~~~~ + +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. + +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 everything 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: ------------------------------------------------ $ git config --global help.format web @@ -8,6 +8,12 @@ #include "exec_cmd.h" #include "common-cmds.h" #include "parse-options.h" +#include "run-command.h" + +static struct man_viewer_list { + void (*exec)(const char *); + struct man_viewer_list *next; +} *man_viewer_list; enum help_format { HELP_FORMAT_MAN, @@ -42,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 + warning("'%s': unsupported man viewer.", value); + + return 0; +} + static int git_help_config(const char *var, const char *value) { if (!strcmp(var, "help.format")) { @@ -50,6 +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")) { + if (!value) + return config_error_nonbool(var); + return add_man_viewer(value); + } return git_default_config(var, value); } @@ -347,9 +454,16 @@ static void setup_man_path(void) 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(); - execlp("man", "man", page, NULL); + 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) |