Merge branch 'ab/help-config-vars'
Teach "git help -c" into helping the command line completion of configuration variables. * ab/help-config-vars: help: move column config discovery to help.c library help / completion: make "git help" do the hard work help tests: test --config-for-completion option & output help: simplify by moving to OPT_CMDMODE() help: correct logic error in combining --all and --guides help: correct logic error in combining --all and --config help tests: add test for --config output help: correct usage & behavior of "git help --guides" help: correct the usage string in -h and documentationmaint
						commit
						62f035aee3
					
				|  | @ -8,8 +8,10 @@ git-help - Display help information about Git | |||
| SYNOPSIS | ||||
| -------- | ||||
| [verse] | ||||
| 'git help' [-a|--all [--[no-]verbose]] [-g|--guides] | ||||
| 	   [-i|--info|-m|--man|-w|--web] [COMMAND|GUIDE] | ||||
| 'git help' [-a|--all [--[no-]verbose]] | ||||
| 	   [[-i|--info] [-m|--man] [-w|--web]] [COMMAND|GUIDE] | ||||
| 'git help' [-g|--guides] | ||||
| 'git help' [-c|--config] | ||||
|  | ||||
| DESCRIPTION | ||||
| ----------- | ||||
|  | @ -58,8 +60,7 @@ OPTIONS | |||
|  | ||||
| -g:: | ||||
| --guides:: | ||||
| 	Prints a list of the Git concept guides on the standard output. This | ||||
| 	option overrides any given command or guide name. | ||||
| 	Prints a list of the Git concept guides on the standard output. | ||||
|  | ||||
| -i:: | ||||
| --info:: | ||||
|  |  | |||
							
								
								
									
										133
									
								
								builtin/help.c
								
								
								
								
							
							
						
						
									
										133
									
								
								builtin/help.c
								
								
								
								
							|  | @ -7,7 +7,6 @@ | |||
| #include "exec-cmd.h" | ||||
| #include "parse-options.h" | ||||
| #include "run-command.h" | ||||
| #include "column.h" | ||||
| #include "config-list.h" | ||||
| #include "help.h" | ||||
| #include "alias.h" | ||||
|  | @ -34,32 +33,52 @@ enum help_format { | |||
| 	HELP_FORMAT_WEB | ||||
| }; | ||||
|  | ||||
| static const char *html_path; | ||||
| enum show_config_type { | ||||
| 	SHOW_CONFIG_HUMAN, | ||||
| 	SHOW_CONFIG_VARS, | ||||
| 	SHOW_CONFIG_SECTIONS, | ||||
| }; | ||||
|  | ||||
| static int show_all = 0; | ||||
| static int show_guides = 0; | ||||
| static int show_config; | ||||
| static enum help_action { | ||||
| 	HELP_ACTION_ALL = 1, | ||||
| 	HELP_ACTION_GUIDES, | ||||
| 	HELP_ACTION_CONFIG, | ||||
| 	HELP_ACTION_CONFIG_FOR_COMPLETION, | ||||
| 	HELP_ACTION_CONFIG_SECTIONS_FOR_COMPLETION, | ||||
| } cmd_mode; | ||||
|  | ||||
| static const char *html_path; | ||||
| static int verbose = 1; | ||||
| static unsigned int colopts; | ||||
| static enum help_format help_format = HELP_FORMAT_NONE; | ||||
| static int exclude_guides; | ||||
| static struct option builtin_help_options[] = { | ||||
| 	OPT_BOOL('a', "all", &show_all, N_("print all available commands")), | ||||
| 	OPT_CMDMODE('a', "all", &cmd_mode, N_("print all available commands"), | ||||
| 		    HELP_ACTION_ALL), | ||||
| 	OPT_HIDDEN_BOOL(0, "exclude-guides", &exclude_guides, N_("exclude guides")), | ||||
| 	OPT_BOOL('g', "guides", &show_guides, N_("print list of useful guides")), | ||||
| 	OPT_BOOL('c', "config", &show_config, N_("print all configuration variable names")), | ||||
| 	OPT_SET_INT_F(0, "config-for-completion", &show_config, "", 2, PARSE_OPT_HIDDEN), | ||||
| 	OPT_SET_INT('m', "man", &help_format, N_("show man page"), HELP_FORMAT_MAN), | ||||
| 	OPT_SET_INT('w', "web", &help_format, N_("show manual in web browser"), | ||||
| 			HELP_FORMAT_WEB), | ||||
| 	OPT_SET_INT('i', "info", &help_format, N_("show info page"), | ||||
| 			HELP_FORMAT_INFO), | ||||
| 	OPT__VERBOSE(&verbose, N_("print command description")), | ||||
|  | ||||
| 	OPT_CMDMODE('g', "guides", &cmd_mode, N_("print list of useful guides"), | ||||
| 		    HELP_ACTION_GUIDES), | ||||
| 	OPT_CMDMODE('c', "config", &cmd_mode, N_("print all configuration variable names"), | ||||
| 		    HELP_ACTION_CONFIG), | ||||
| 	OPT_CMDMODE_F(0, "config-for-completion", &cmd_mode, "", | ||||
| 		    HELP_ACTION_CONFIG_FOR_COMPLETION, PARSE_OPT_HIDDEN), | ||||
| 	OPT_CMDMODE_F(0, "config-sections-for-completion", &cmd_mode, "", | ||||
| 		    HELP_ACTION_CONFIG_SECTIONS_FOR_COMPLETION, PARSE_OPT_HIDDEN), | ||||
|  | ||||
| 	OPT_END(), | ||||
| }; | ||||
|  | ||||
| static const char * const builtin_help_usage[] = { | ||||
| 	N_("git help [--all] [--guides] [--man | --web | --info] [<command>]"), | ||||
| 	N_("git help [-a|--all] [--[no-]verbose]]\n" | ||||
| 	   "         [[-i|--info] [-m|--man] [-w|--web]] [<command>]"), | ||||
| 	N_("git help [-g|--guides]"), | ||||
| 	N_("git help [-c|--config]"), | ||||
| 	NULL | ||||
| }; | ||||
|  | ||||
|  | @ -70,7 +89,7 @@ struct slot_expansion { | |||
| 	int found; | ||||
| }; | ||||
|  | ||||
| static void list_config_help(int for_human) | ||||
| static void list_config_help(enum show_config_type type) | ||||
| { | ||||
| 	struct slot_expansion slot_expansions[] = { | ||||
| 		{ "advice", "*", list_config_advices }, | ||||
|  | @ -88,6 +107,8 @@ static void list_config_help(int for_human) | |||
| 	const char **p; | ||||
| 	struct slot_expansion *e; | ||||
| 	struct string_list keys = STRING_LIST_INIT_DUP; | ||||
| 	struct string_list keys_uniq = STRING_LIST_INIT_DUP; | ||||
| 	struct string_list_item *item; | ||||
| 	int i; | ||||
|  | ||||
| 	for (p = config_name_list; *p; p++) { | ||||
|  | @ -118,34 +139,46 @@ static void list_config_help(int for_human) | |||
| 	for (i = 0; i < keys.nr; i++) { | ||||
| 		const char *var = keys.items[i].string; | ||||
| 		const char *wildcard, *tag, *cut; | ||||
| 		const char *dot = NULL; | ||||
| 		struct strbuf sb = STRBUF_INIT; | ||||
|  | ||||
| 		if (for_human) { | ||||
| 		switch (type) { | ||||
| 		case SHOW_CONFIG_HUMAN: | ||||
| 			puts(var); | ||||
| 			continue; | ||||
| 		case SHOW_CONFIG_SECTIONS: | ||||
| 			dot = strchr(var, '.'); | ||||
| 			break; | ||||
| 		case SHOW_CONFIG_VARS: | ||||
| 			break; | ||||
| 		} | ||||
|  | ||||
| 		wildcard = strchr(var, '*'); | ||||
| 		tag = strchr(var, '<'); | ||||
|  | ||||
| 		if (!wildcard && !tag) { | ||||
| 			puts(var); | ||||
| 		if (!dot && !wildcard && !tag) { | ||||
| 			string_list_append(&keys_uniq, var); | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		if (wildcard && !tag) | ||||
| 		if (dot) | ||||
| 			cut = dot; | ||||
| 		else if (wildcard && !tag) | ||||
| 			cut = wildcard; | ||||
| 		else if (!wildcard && tag) | ||||
| 			cut = tag; | ||||
| 		else | ||||
| 			cut = wildcard < tag ? wildcard : tag; | ||||
|  | ||||
| 		/* | ||||
| 		 * We may produce duplicates, but that's up to | ||||
| 		 * git-completion.bash to handle | ||||
| 		 */ | ||||
| 		printf("%.*s\n", (int)(cut - var), var); | ||||
| 		strbuf_add(&sb, var, cut - var); | ||||
| 		string_list_append(&keys_uniq, sb.buf); | ||||
| 		strbuf_release(&sb); | ||||
|  | ||||
| 	} | ||||
| 	string_list_clear(&keys, 0); | ||||
| 	string_list_remove_duplicates(&keys_uniq, 0); | ||||
| 	for_each_string_list_item(item, &keys_uniq) | ||||
| 		puts(item->string); | ||||
| 	string_list_clear(&keys_uniq, 0); | ||||
| } | ||||
|  | ||||
| static enum help_format parse_help_format(const char *format) | ||||
|  | @ -349,8 +382,6 @@ static int add_man_viewer_info(const char *var, const char *value) | |||
|  | ||||
| static int git_help_config(const char *var, const char *value, void *cb) | ||||
| { | ||||
| 	if (starts_with(var, "column.")) | ||||
| 		return git_column_config(var, value, "help", &colopts); | ||||
| 	if (!strcmp(var, "help.format")) { | ||||
| 		if (!value) | ||||
| 			return config_error_nonbool(var); | ||||
|  | @ -544,6 +575,13 @@ static const char *check_git_cmd(const char* cmd) | |||
| 	return cmd; | ||||
| } | ||||
|  | ||||
| static void no_extra_argc(int argc) | ||||
| { | ||||
| 	if (argc) | ||||
| 		usage_msg_opt(_("this option doesn't take any other arguments"), | ||||
| 			      builtin_help_usage, builtin_help_options); | ||||
| } | ||||
|  | ||||
| int cmd_help(int argc, const char **argv, const char *prefix) | ||||
| { | ||||
| 	int nongit; | ||||
|  | @ -554,8 +592,8 @@ int cmd_help(int argc, const char **argv, const char *prefix) | |||
| 			builtin_help_usage, 0); | ||||
| 	parsed_help_format = help_format; | ||||
|  | ||||
| 	if (show_all) { | ||||
| 		git_config(git_help_config, NULL); | ||||
| 	switch (cmd_mode) { | ||||
| 	case HELP_ACTION_ALL: | ||||
| 		if (verbose) { | ||||
| 			setup_pager(); | ||||
| 			list_all_cmds_help(); | ||||
|  | @ -563,30 +601,27 @@ int cmd_help(int argc, const char **argv, const char *prefix) | |||
| 		} | ||||
| 		printf(_("usage: %s%s"), _(git_usage_string), "\n\n"); | ||||
| 		load_command_list("git-", &main_cmds, &other_cmds); | ||||
| 		list_commands(colopts, &main_cmds, &other_cmds); | ||||
| 	} | ||||
|  | ||||
| 	if (show_config) { | ||||
| 		int for_human = show_config == 1; | ||||
|  | ||||
| 		if (!for_human) { | ||||
| 			list_config_help(for_human); | ||||
| 			return 0; | ||||
| 		} | ||||
| 		setup_pager(); | ||||
| 		list_config_help(for_human); | ||||
| 		printf("\n%s\n", _("'git help config' for more information")); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
| 	if (show_guides) | ||||
| 		list_guides_help(); | ||||
|  | ||||
| 	if (show_all || show_guides) { | ||||
| 		list_commands(&main_cmds, &other_cmds); | ||||
| 		printf("%s\n", _(git_more_info_string)); | ||||
| 		/* | ||||
| 		* We're done. Ignore any remaining args | ||||
| 		*/ | ||||
| 		break; | ||||
| 	case HELP_ACTION_GUIDES: | ||||
| 		no_extra_argc(argc); | ||||
| 		list_guides_help(); | ||||
| 		printf("%s\n", _(git_more_info_string)); | ||||
| 		return 0; | ||||
| 	case HELP_ACTION_CONFIG_FOR_COMPLETION: | ||||
| 		no_extra_argc(argc); | ||||
| 		list_config_help(SHOW_CONFIG_VARS); | ||||
| 		return 0; | ||||
| 	case HELP_ACTION_CONFIG_SECTIONS_FOR_COMPLETION: | ||||
| 		no_extra_argc(argc); | ||||
| 		list_config_help(SHOW_CONFIG_SECTIONS); | ||||
| 		return 0; | ||||
| 	case HELP_ACTION_CONFIG: | ||||
| 		no_extra_argc(argc); | ||||
| 		setup_pager(); | ||||
| 		list_config_help(SHOW_CONFIG_HUMAN); | ||||
| 		printf("\n%s\n", _("'git help config' for more information")); | ||||
| 		return 0; | ||||
| 	} | ||||
|  | ||||
|  |  | |||
|  | @ -2503,7 +2503,14 @@ __git_config_vars= | |||
| __git_compute_config_vars () | ||||
| { | ||||
| 	test -n "$__git_config_vars" || | ||||
| 	__git_config_vars="$(git help --config-for-completion | sort -u)" | ||||
| 	__git_config_vars="$(git help --config-for-completion)" | ||||
| } | ||||
|  | ||||
| __git_config_sections= | ||||
| __git_compute_config_sections () | ||||
| { | ||||
| 	test -n "$__git_config_sections" || | ||||
| 	__git_config_sections="$(git help --config-sections-for-completion)" | ||||
| } | ||||
|  | ||||
| # Completes possible values of various configuration variables. | ||||
|  | @ -2717,16 +2724,8 @@ __git_complete_config_variable_name () | |||
| 		__gitcomp "$__git_config_vars" "" "$cur_" "$sfx" | ||||
| 		;; | ||||
| 	*) | ||||
| 		__git_compute_config_vars | ||||
| 		__gitcomp "$(echo "$__git_config_vars" | | ||||
| 				awk -F . '{ | ||||
| 					sections[$1] = 1 | ||||
| 				} | ||||
| 				END { | ||||
| 					for (s in sections) | ||||
| 						print s "." | ||||
| 				} | ||||
| 				')" "" "$cur_" | ||||
| 		__git_compute_config_sections | ||||
| 		__gitcomp "$__git_config_sections" "" "$cur_" "." | ||||
| 		;; | ||||
| 	esac | ||||
| } | ||||
|  |  | |||
							
								
								
									
										16
									
								
								help.c
								
								
								
								
							
							
						
						
									
										16
									
								
								help.c
								
								
								
								
							|  | @ -293,9 +293,21 @@ void load_command_list(const char *prefix, | |||
| 	exclude_cmds(other_cmds, main_cmds); | ||||
| } | ||||
|  | ||||
| void list_commands(unsigned int colopts, | ||||
| 		   struct cmdnames *main_cmds, struct cmdnames *other_cmds) | ||||
| static int get_colopts(const char *var, const char *value, void *data) | ||||
| { | ||||
| 	unsigned int *colopts = data; | ||||
|  | ||||
| 	if (starts_with(var, "column.")) | ||||
| 		return git_column_config(var, value, "help", colopts); | ||||
|  | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| void list_commands(struct cmdnames *main_cmds, struct cmdnames *other_cmds) | ||||
| { | ||||
| 	unsigned int colopts = 0; | ||||
| 	git_config(get_colopts, &colopts); | ||||
|  | ||||
| 	if (main_cmds->cnt) { | ||||
| 		const char *exec_path = git_exec_path(); | ||||
| 		printf_ln(_("available git commands in '%s'"), exec_path); | ||||
|  |  | |||
							
								
								
									
										2
									
								
								help.h
								
								
								
								
							
							
						
						
									
										2
									
								
								help.h
								
								
								
								
							|  | @ -37,7 +37,7 @@ void add_cmdname(struct cmdnames *cmds, const char *name, int len); | |||
| /* Here we require that excludes is a sorted list. */ | ||||
| void exclude_cmds(struct cmdnames *cmds, struct cmdnames *excludes); | ||||
| int is_in_cmdlist(struct cmdnames *cmds, const char *name); | ||||
| void list_commands(unsigned int colopts, struct cmdnames *main_cmds, struct cmdnames *other_cmds); | ||||
| void list_commands(struct cmdnames *main_cmds, struct cmdnames *other_cmds); | ||||
| void get_version_info(struct strbuf *buf, int show_build_options); | ||||
|  | ||||
| /* | ||||
|  |  | |||
|  | @ -166,8 +166,10 @@ struct option { | |||
| #define OPT_BOOL(s, l, v, h)        OPT_BOOL_F(s, l, v, h, 0) | ||||
| #define OPT_HIDDEN_BOOL(s, l, v, h) { OPTION_SET_INT, (s), (l), (v), NULL, \ | ||||
| 				      (h), PARSE_OPT_NOARG | PARSE_OPT_HIDDEN, NULL, 1} | ||||
| #define OPT_CMDMODE(s, l, v, h, i)  { OPTION_SET_INT, (s), (l), (v), NULL, \ | ||||
| 				      (h), PARSE_OPT_CMDMODE|PARSE_OPT_NOARG|PARSE_OPT_NONEG, NULL, (i) } | ||||
| #define OPT_CMDMODE_F(s, l, v, h, i, f)  { OPTION_SET_INT, (s), (l), (v), NULL, \ | ||||
| 				      (h), PARSE_OPT_CMDMODE|PARSE_OPT_NOARG|PARSE_OPT_NONEG | (f), NULL, (i) } | ||||
| #define OPT_CMDMODE(s, l, v, h, i)  OPT_CMDMODE_F(s, l, v, h, i, 0) | ||||
|  | ||||
| #define OPT_INTEGER(s, l, v, h)     OPT_INTEGER_F(s, l, v, h, 0) | ||||
| #define OPT_MAGNITUDE(s, l, v, h)   { OPTION_MAGNITUDE, (s), (l), (v), \ | ||||
| 				      N_("n"), (h), PARSE_OPT_NONEG } | ||||
|  |  | |||
|  | @ -34,6 +34,18 @@ test_expect_success 'basic help commands' ' | |||
| 	git help -a >/dev/null | ||||
| ' | ||||
|  | ||||
| test_expect_success 'invalid usage' ' | ||||
| 	test_expect_code 129 git help -g add && | ||||
| 	test_expect_code 129 git help -a -c && | ||||
|  | ||||
| 	test_expect_code 129 git help -g add && | ||||
| 	test_expect_code 129 git help -a -g && | ||||
|  | ||||
| 	test_expect_code 129 git help -g -c && | ||||
| 	test_expect_code 129 git help --config-for-completion add && | ||||
| 	test_expect_code 129 git help --config-sections-for-completion add | ||||
| ' | ||||
|  | ||||
| test_expect_success "works for commands and guides by default" ' | ||||
| 	configure_help && | ||||
| 	git help status && | ||||
|  | @ -89,6 +101,43 @@ test_expect_success 'git help succeeds without git.html' ' | |||
| 	test_cmp expect test-browser.log | ||||
| ' | ||||
|  | ||||
| test_expect_success 'git help -c' ' | ||||
| 	git help -c >help.output && | ||||
| 	cat >expect <<-\EOF && | ||||
|  | ||||
| 	'\''git help config'\'' for more information | ||||
| 	EOF | ||||
| 	grep -v -E \ | ||||
| 		-e "^[^.]+\.[^.]+$" \ | ||||
| 		-e "^[^.]+\.[^.]+\.[^.]+$" \ | ||||
| 		help.output >actual && | ||||
| 	test_cmp expect actual | ||||
| ' | ||||
|  | ||||
| test_expect_success 'git help --config-for-completion' ' | ||||
| 	git help -c >human && | ||||
| 	grep -E \ | ||||
| 	     -e "^[^.]+\.[^.]+$" \ | ||||
| 	     -e "^[^.]+\.[^.]+\.[^.]+$" human | | ||||
| 	     sed -e "s/\*.*//" -e "s/<.*//" | | ||||
| 	     sort -u >human.munged && | ||||
|  | ||||
| 	git help --config-for-completion >vars && | ||||
| 	test_cmp human.munged vars | ||||
| ' | ||||
|  | ||||
| test_expect_success 'git help --config-sections-for-completion' ' | ||||
| 	git help -c >human && | ||||
| 	grep -E \ | ||||
| 	     -e "^[^.]+\.[^.]+$" \ | ||||
| 	     -e "^[^.]+\.[^.]+\.[^.]+$" human | | ||||
| 	     sed -e "s/\..*//" | | ||||
| 	     sort -u >human.munged && | ||||
|  | ||||
| 	git help --config-sections-for-completion >sections && | ||||
| 	test_cmp human.munged sections | ||||
| ' | ||||
|  | ||||
| test_expect_success 'generate builtin list' ' | ||||
| 	git --list-cmds=builtins >builtins | ||||
| ' | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Junio C Hamano
						Junio C Hamano