X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=help.c;h=e57a50ed59badbb968ce508b6c1802f1fcb68903;hb=70f5d5d31cbf0ba273083805124ad67135142527;hp=d340b6a1b6c4ecb8132e81fe306883aa18feb090;hpb=80bbe72b76ab91628b493b55ed74f6eec8432fed;p=git.git diff --git a/help.c b/help.c index d340b6a1b..e57a50ed5 100644 --- a/help.c +++ b/help.c @@ -7,6 +7,51 @@ #include "builtin.h" #include "exec_cmd.h" #include "common-cmds.h" +#include "parse-options.h" + +enum help_format { + HELP_FORMAT_MAN, + HELP_FORMAT_INFO, + HELP_FORMAT_WEB, +}; + +static int show_all = 0; +static enum help_format help_format = HELP_FORMAT_MAN; +static struct option builtin_help_options[] = { + OPT_BOOLEAN('a', "all", &show_all, "print all available commands"), + OPT_SET_INT('m', "man", &help_format, "show man page", HELP_FORMAT_MAN), + OPT_SET_INT('w', "web", &help_format, "show manual in web browser", + HELP_FORMAT_WEB), + OPT_SET_INT('i', "info", &help_format, "show info page", + HELP_FORMAT_INFO), +}; + +static const char * const builtin_help_usage[] = { + "git-help [--all] [--man|--web|--info] [command]", + NULL +}; + +static enum help_format parse_help_format(const char *format) +{ + if (!strcmp(format, "man")) + return HELP_FORMAT_MAN; + if (!strcmp(format, "info")) + return HELP_FORMAT_INFO; + if (!strcmp(format, "web") || !strcmp(format, "html")) + return HELP_FORMAT_WEB; + die("unrecognized help format '%s'", format); +} + +static int git_help_config(const char *var, const char *value) +{ + if (!strcmp(var, "help.format")) { + if (!value) + return config_error_nonbool(var); + help_format = parse_help_format(value); + return 0; + } + return git_default_config(var, value); +} /* most GUI terminals set COLUMNS (although some don't export it) */ static int term_columns(void) @@ -165,7 +210,7 @@ static unsigned int list_commands_in_dir(struct cmdnames *cmds, return longest; } -static void list_commands(void) +static unsigned int load_command_list(void) { unsigned int longest = 0; unsigned int len; @@ -205,6 +250,14 @@ static void list_commands(void) uniq(&other_cmds); exclude_cmds(&other_cmds, &main_cmds); + return longest; +} + +static void list_commands(void) +{ + unsigned int longest = load_command_list(); + const char *exec_path = git_exec_path(); + if (main_cmds.cnt) { printf("available git commands in '%s'\n", exec_path); printf("----------------------------"); @@ -237,27 +290,97 @@ void list_common_cmds_help(void) mput_char(' ', longest - strlen(common_cmds[i].name)); puts(common_cmds[i].help); } - puts("(use 'git help -a' to get a list of all installed git commands)"); } -static void show_man_page(const char *git_cmd) +static int is_in_cmdlist(struct cmdnames *c, const char *s) { - const char *page; + int i; + for (i = 0; i < c->cnt; i++) + if (!strcmp(s, c->names[i]->name)) + return 1; + return 0; +} - if (!prefixcmp(git_cmd, "git")) - page = git_cmd; +static int is_git_command(const char *s) +{ + load_command_list(); + return is_in_cmdlist(&main_cmds, s) || + is_in_cmdlist(&other_cmds, s); +} + +static const char *cmd_to_page(const char *git_cmd) +{ + if (!git_cmd) + return "git"; + else if (!prefixcmp(git_cmd, "git")) + return git_cmd; else { int page_len = strlen(git_cmd) + 4; char *p = xmalloc(page_len + 1); strcpy(p, "git-"); strcpy(p + 4, git_cmd); p[page_len] = 0; - page = p; + return p; } +} + +static void setup_man_path(void) +{ + struct strbuf new_path; + const char *old_path = getenv("MANPATH"); + + strbuf_init(&new_path, 0); + /* We should always put ':' after our path. If there is no + * old_path, the ':' at the end will let 'man' to try + * system-wide paths after ours to find the manual page. If + * there is old_path, we need ':' as delimiter. */ + strbuf_addstr(&new_path, GIT_MAN_PATH); + strbuf_addch(&new_path, ':'); + if (old_path) + strbuf_addstr(&new_path, old_path); + + setenv("MANPATH", new_path.buf, 1); + + strbuf_release(&new_path); +} + +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); } +static void show_info_page(const char *git_cmd) +{ + const char *page = cmd_to_page(git_cmd); + setenv("INFOPATH", GIT_INFO_PATH, 1); + execlp("info", "info", "gitman", page, NULL); +} + +static void get_html_page_path(struct strbuf *page_path, const char *page) +{ + struct stat st; + + /* Check that we have a git documentation directory. */ + if (stat(GIT_HTML_PATH "/git.html", &st) || !S_ISREG(st.st_mode)) + die("'%s': not a documentation directory.", GIT_HTML_PATH); + + strbuf_init(page_path, 0); + strbuf_addf(page_path, GIT_HTML_PATH "/%s.html", page); +} + +static void show_html_page(const char *git_cmd) +{ + const char *page = cmd_to_page(git_cmd); + struct strbuf page_path; /* it leaks but we exec bellow */ + + get_html_page_path(&page_path, page); + + execl_git_cmd("web--browse", "-c", "help.browser", page_path.buf, NULL); +} + void help_unknown_cmd(const char *cmd) { fprintf(stderr, "git: '%s' is not a git-command. See 'git --help'.\n", cmd); @@ -272,22 +395,44 @@ int cmd_version(int argc, const char **argv, const char *prefix) int cmd_help(int argc, const char **argv, const char *prefix) { - const char *help_cmd = argc > 1 ? argv[1] : NULL; + int nongit; + const char *alias; + + setup_git_directory_gently(&nongit); + git_config(git_help_config); + + argc = parse_options(argc, argv, builtin_help_options, + builtin_help_usage, 0); - if (!help_cmd) { + if (show_all) { printf("usage: %s\n\n", git_usage_string); - list_common_cmds_help(); - exit(0); + list_commands(); + return 0; } - else if (!strcmp(help_cmd, "--all") || !strcmp(help_cmd, "-a")) { + if (!argv[0]) { printf("usage: %s\n\n", git_usage_string); - list_commands(); - exit(0); + list_common_cmds_help(); + return 0; } - else - show_man_page(help_cmd); + alias = alias_lookup(argv[0]); + if (alias && !is_git_command(argv[0])) { + printf("`git %s' is aliased to `%s'\n", argv[0], alias); + return 0; + } + + switch (help_format) { + case HELP_FORMAT_MAN: + show_man_page(argv[0]); + break; + case HELP_FORMAT_INFO: + show_info_page(argv[0]); + break; + case HELP_FORMAT_WEB: + show_html_page(argv[0]); + break; + } return 0; }