git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* [PATCH 0/2] Dynamic long options for bash completion
@ 2012-04-11 10:29 Stephen Boyd
  2012-04-11 10:29 ` [PATCH 1/2] parse-options: Add support for dumping out long options Stephen Boyd
  2012-04-11 10:29 ` [PATCH 2/2] completion: Use parse-options raw output for simple " Stephen Boyd
  0 siblings, 2 replies; 14+ messages in thread
From: Stephen Boyd @ 2012-04-11 10:29 UTC (permalink / raw)
  To: git; +Cc: spearce, szeder, felipe.contreras, jrnieder

I've been meaning to do this for a while. I realize we gain some more
lines but it seems better to just generate these lists automatically
instead of managing them by hand.

Stephen Boyd (2):
  parse-options: Add support for dumping out long options
  completion: Use parse-options raw output for simple long options

 contrib/completion/git-completion.bash |  298 +++++++++++++++++++-------------
 parse-options.c                        |   41 +++++
 2 files changed, 217 insertions(+), 122 deletions(-)

-- 
1.7.10.128.g7945c.dirty

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [PATCH 1/2] parse-options: Add support for dumping out long options
  2012-04-11 10:29 [PATCH 0/2] Dynamic long options for bash completion Stephen Boyd
@ 2012-04-11 10:29 ` Stephen Boyd
  2012-04-11 10:51   ` Felipe Contreras
                     ` (2 more replies)
  2012-04-11 10:29 ` [PATCH 2/2] completion: Use parse-options raw output for simple " Stephen Boyd
  1 sibling, 3 replies; 14+ messages in thread
From: Stephen Boyd @ 2012-04-11 10:29 UTC (permalink / raw)
  To: git; +Cc: spearce, szeder, felipe.contreras, jrnieder

The bash completion script wants to know what the long options are for a
certain command at runtime. Add a magical long option that nobody could
possibly ever use (--dump-raw-long-options) to get this information.

Some example output:

 $ git clone --dump-raw-long-options
 --no-verbose --no-quiet --progress --no-progress --no-checkout
 --checkout --bare --no-bare --mirror --no-mirror --local --no-local
 --no-hardlinks --hardlinks --shared --no-shared --recursive
 --no-recursive --recurse-submodules --no-recurse-submodules --template=
 --no-template --reference= --no-reference --origin= --no-origin
 --branch= --no-branch --upload-pack= --no-upload-pack --depth=
 --no-depth --single-branch --no-single-branch --separate-git-dir=
 --no-separate-git-dir --config= --no-config

Signed-off-by: Stephen Boyd <bebarino@gmail.com>
---

The name can be anything. This seemed sufficiently obscure.

 parse-options.c |   41 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 41 insertions(+)

diff --git a/parse-options.c b/parse-options.c
index 850cfa7..6c37497 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -364,6 +364,45 @@ static int usage_with_options_internal(struct parse_opt_ctx_t *,
 				       const char * const *,
 				       const struct option *, int, int);
 
+static int parse_options_raw(const struct option *opts)
+{
+	for (; opts->type != OPTION_END; opts++) {
+		if (opts->flags & PARSE_OPT_HIDDEN)
+			continue;
+		if (!opts->long_name)
+			continue;
+		switch (opts->type) {
+		case OPTION_BIT:
+		case OPTION_NEGBIT:
+		case OPTION_COUNTUP:
+		case OPTION_SET_INT:
+		case OPTION_SET_PTR:
+			fprintf(stdout, "--%s ", opts->long_name);
+			break;
+		case OPTION_LOWLEVEL_CALLBACK:
+		case OPTION_STRING:
+		case OPTION_FILENAME:
+		case OPTION_INTEGER:
+		case OPTION_CALLBACK:
+			if (opts->flags & PARSE_OPT_OPTARG)
+				fprintf(stdout, "--%s ", opts->long_name);
+			else if (!(opts->flags & PARSE_OPT_NOARG))
+				fprintf(stdout, "--%s= ", opts->long_name);
+			break;
+		default:
+			continue;
+		}
+		if (!(opts->flags & PARSE_OPT_NONEG)) {
+			if (!prefixcmp(opts->long_name, "no-"))
+				fprintf(stdout, "--%s ", opts->long_name + 3);
+			else
+				fprintf(stdout, "--no-%s ", opts->long_name);
+		}
+	}
+
+	return PARSE_OPT_HELP;
+}
+
 int parse_options_step(struct parse_opt_ctx_t *ctx,
 		       const struct option *options,
 		       const char * const usagestr[])
@@ -431,6 +470,8 @@ int parse_options_step(struct parse_opt_ctx_t *ctx,
 			return usage_with_options_internal(ctx, usagestr, options, 1, 0);
 		if (internal_help && !strcmp(arg + 2, "help"))
 			return parse_options_usage(ctx, usagestr, options, 0);
+		if (!strcmp(arg + 2, "dump-raw-long-options"))
+			return parse_options_raw(options);
 		switch (parse_long_opt(ctx, arg + 2, options)) {
 		case -1:
 			return parse_options_usage(ctx, usagestr, options, 1);
-- 
1.7.10.128.g7945c.dirty

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/2] completion: Use parse-options raw output for simple long options
  2012-04-11 10:29 [PATCH 0/2] Dynamic long options for bash completion Stephen Boyd
  2012-04-11 10:29 ` [PATCH 1/2] parse-options: Add support for dumping out long options Stephen Boyd
@ 2012-04-11 10:29 ` Stephen Boyd
  2012-04-11 13:09   ` Jonathan Nieder
                     ` (2 more replies)
  1 sibling, 3 replies; 14+ messages in thread
From: Stephen Boyd @ 2012-04-11 10:29 UTC (permalink / raw)
  To: git; +Cc: spearce, szeder, felipe.contreras, jrnieder

Now that parse-options supports generating lists of long options for any
parse-optified git program we can remove the hand-coded lists in the
completion script. Replace these lists with code to generate the lists
lazily when a user tab completes that specific command. Unforunately,
doing lazy evalution takes more lines than before, but the benefit is we
reduce the amount of trivial patches to update the script for new and/or
removed options. It also mildly encourages the migration of git commands
to the parse-options API.

Signed-off-by: Stephen Boyd <bebarino@gmail.com>
---

Is there some way to compute these lists with some magical function instead
of duplicating that logic over and over?

 contrib/completion/git-completion.bash |  298 +++++++++++++++++++-------------
 1 file changed, 176 insertions(+), 122 deletions(-)

diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 31f714d..69abbe5 100755
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -917,6 +917,11 @@ __git_list_porcelain_commands ()
 	done
 }
 
+__git_list_command_options ()
+{
+	git $@ --dump-raw-long-options
+}
+
 __git_porcelain_commands=
 __git_compute_porcelain_commands ()
 {
@@ -1027,43 +1032,45 @@ _git_am ()
 	COMPREPLY=()
 }
 
+__git_apply_options=
 _git_apply ()
 {
+	test -n "$__git_apply_options" ||
+	__git_apply_options=$(__git_list_command_options apply)
+
 	case "$cur" in
 	--whitespace=*)
 		__gitcomp "$__git_whitespacelist" "" "${cur##--whitespace=}"
 		return
 		;;
 	--*)
-		__gitcomp "
-			--stat --numstat --summary --check --index
-			--cached --index-info --reverse --reject --unidiff-zero
-			--apply --no-add --exclude=
-			--ignore-whitespace --ignore-space-change
-			--whitespace= --inaccurate-eof --verbose
-			"
+		__gitcomp "$__git_apply_options"
 		return
 	esac
 	COMPREPLY=()
 }
 
+__git_add_options=
 _git_add ()
 {
 	__git_has_doubledash && return
+	test -n "$__git_add_options" ||
+	__git_add_options=$(__git_list_command_options add)
 
 	case "$cur" in
 	--*)
-		__gitcomp "
-			--interactive --refresh --patch --update --dry-run
-			--ignore-errors --intent-to-add
-			"
+		__gitcomp "$__git_add_options"
 		return
 	esac
 	COMPREPLY=()
 }
 
+__git_archive_options=
 _git_archive ()
 {
+	test -n "$__git_archive_options" ||
+	__git_archive_options=$(__git_list_command_options archive)
+
 	case "$cur" in
 	--format=*)
 		__gitcomp "$(git archive --list)" "" "${cur##--format=}"
@@ -1074,10 +1081,7 @@ _git_archive ()
 		return
 		;;
 	--*)
-		__gitcomp "
-			--format= --list --verbose
-			--prefix= --remote= --exec=
-			"
+		__gitcomp "$__git_archive_options"
 		return
 		;;
 	esac
@@ -1109,6 +1113,7 @@ _git_bisect ()
 	esac
 }
 
+__git_branch_options=
 _git_branch ()
 {
 	local i c=1 only_local_ref="n" has_r="n"
@@ -1122,13 +1127,12 @@ _git_branch ()
 		((c++))
 	done
 
+	test -n "$__git_branch_options" ||
+	__git_branch_options=$(__git_list_command_options branch)
+
 	case "$cur" in
 	--*)
-		__gitcomp "
-			--color --no-color --verbose --abbrev= --no-abbrev
-			--track --no-track --contains --merged --no-merged
-			--set-upstream --edit-description --list
-			"
+		__gitcomp "$__git_branch_options"
 		;;
 	*)
 		if [ $only_local_ref = "y" -a $has_r = "n" ]; then
@@ -1160,19 +1164,19 @@ _git_bundle ()
 	esac
 }
 
+__git_checkout_options=
 _git_checkout ()
 {
 	__git_has_doubledash && return
+	test -n "$__git_checkout_options" ||
+	__git_checkout_options=$(__git_list_command_options checkout)
 
 	case "$cur" in
 	--conflict=*)
 		__gitcomp "diff3 merge" "" "${cur##--conflict=}"
 		;;
 	--*)
-		__gitcomp "
-			--quiet --ours --theirs --track --no-track --merge
-			--conflict= --orphan --patch
-			"
+		__gitcomp "$__git_checkout_options"
 		;;
 	*)
 		# check if --track, --no-track, or --no-guess was specified
@@ -1191,11 +1195,15 @@ _git_cherry ()
 	__gitcomp "$(__git_refs)"
 }
 
+__git_cherry_pick_options=
 _git_cherry_pick ()
 {
+	test -n "$__git_cherry_pick_options" ||
+	__git_cherry_pick_options=$(__git_list_command_options cherry-pick)
+
 	case "$cur" in
 	--*)
-		__gitcomp "--edit --no-commit"
+		__gitcomp "$__git_cherry_pick_options"
 		;;
 	*)
 		__gitcomp_nl "$(__git_refs)"
@@ -1203,46 +1211,44 @@ _git_cherry_pick ()
 	esac
 }
 
+__git_clean_options=
 _git_clean ()
 {
 	__git_has_doubledash && return
 
+	test -n "$__git_clean_options" ||
+	__git_clean_options=$(__git_list_command_options clean)
+
 	case "$cur" in
 	--*)
-		__gitcomp "--dry-run --quiet"
+		__gitcomp "$__git_clean_options"
 		return
 		;;
 	esac
 	COMPREPLY=()
 }
 
+__git_clone_options=
 _git_clone ()
 {
+	test -n "$__git_clone_options" ||
+	__git_clone_options=$(__git_list_command_options clone)
+
 	case "$cur" in
 	--*)
-		__gitcomp "
-			--local
-			--no-hardlinks
-			--shared
-			--reference
-			--quiet
-			--no-checkout
-			--bare
-			--mirror
-			--origin
-			--upload-pack
-			--template=
-			--depth
-			"
+		__gitcomp "$__git_clone_options"
 		return
 		;;
 	esac
 	COMPREPLY=()
 }
 
+__git_commit_options=
 _git_commit ()
 {
 	__git_has_doubledash && return
+	test -n "$__git_commit_options" ||
+	__git_commit_options=$(__git_list_command_options commit)
 
 	case "$cur" in
 	--cleanup=*)
@@ -1260,27 +1266,21 @@ _git_commit ()
 		return
 		;;
 	--*)
-		__gitcomp "
-			--all --author= --signoff --verify --no-verify
-			--edit --amend --include --only --interactive
-			--dry-run --reuse-message= --reedit-message=
-			--reset-author --file= --message= --template=
-			--cleanup= --untracked-files --untracked-files=
-			--verbose --quiet --fixup= --squash=
-			"
+		__gitcomp "$__git_commit_options"
 		return
 	esac
 	COMPREPLY=()
 }
 
+__git_describe_options=
 _git_describe ()
 {
+	test -n "$__git_describe_options" ||
+	__git_describe_options=$(__git_list_command_options describe)
+
 	case "$cur" in
 	--*)
-		__gitcomp "
-			--all --tags --contains --abbrev= --candidates=
-			--exact-match --debug --long --match --always
-			"
+		__gitcomp "$__git_describe_options"
 		return
 	esac
 	__gitcomp_nl "$(__git_refs)"
@@ -1343,13 +1343,16 @@ _git_difftool ()
 	__git_complete_file
 }
 
-__git_fetch_options="
-	--quiet --verbose --append --upload-pack --force --keep --depth=
-	--tags --no-tags --all --prune --dry-run
-"
+__git_fetch_options=
+__git_compute_fetch_options ()
+{
+	test -n "$__git_fetch_options" ||
+	__git_fetch_options=$(__git_list_command_options fetch)
+}
 
 _git_fetch ()
 {
+	__git_compute_fetch_options
 	case "$cur" in
 	--*)
 		__gitcomp "$__git_fetch_options"
@@ -1359,8 +1362,12 @@ _git_fetch ()
 	__git_complete_remote_or_refspec
 }
 
+__git_format_patch_options=
 _git_format_patch ()
 {
+	test -n "$__git_format_patch_options" ||
+	__git_format_patch_options=$(__git_list_command_options format-patch)
+
 	case "$cur" in
 	--thread=*)
 		__gitcomp "
@@ -1369,46 +1376,37 @@ _git_format_patch ()
 		return
 		;;
 	--*)
-		__gitcomp "
-			--stdout --attach --no-attach --thread --thread=
-			--output-directory
-			--numbered --start-number
-			--numbered-files
-			--keep-subject
-			--signoff --signature --no-signature
-			--in-reply-to= --cc=
-			--full-index --binary
-			--not --all
-			--cover-letter
-			--no-prefix --src-prefix= --dst-prefix=
-			--inline --suffix= --ignore-if-in-upstream
-			--subject-prefix=
-			"
+		__gitcomp "$__git_format_patch_options"
 		return
 		;;
 	esac
 	__git_complete_revlist
 }
 
+__git_fsck_options=
 _git_fsck ()
 {
+	test -n "$__git_fsck_options" ||
+	__git_fsck_options=$(__git_list_command_options fsck)
+
 	case "$cur" in
 	--*)
-		__gitcomp "
-			--tags --root --unreachable --cache --no-reflogs --full
-			--strict --verbose --lost-found
-			"
+		__gitcomp "$__git_fsck_options"
 		return
 		;;
 	esac
 	COMPREPLY=()
 }
 
+__git_gc_options=
 _git_gc ()
 {
+	test -n "$__git_gc_options" ||
+	__git_gc_options=$(__git_list_command_options gc)
+
 	case "$cur" in
 	--*)
-		__gitcomp "--prune --aggressive"
+		__gitcomp "$__git_gc_options"
 		return
 		;;
 	esac
@@ -1424,24 +1422,17 @@ __git_match_ctag() {
 	awk "/^${1////\\/}/ { print \$1 }" "$2"
 }
 
+__git_grep_options=
 _git_grep ()
 {
 	__git_has_doubledash && return
 
+	test -n "$__git_grep_options" ||
+	__git_grep_options=$(__git_list_command_options grep)
+
 	case "$cur" in
 	--*)
-		__gitcomp "
-			--cached
-			--text --ignore-case --word-regexp --invert-match
-			--full-name --line-number
-			--extended-regexp --basic-regexp --fixed-strings
-			--perl-regexp
-			--files-with-matches --name-only
-			--files-without-match
-			--max-depth
-			--count
-			--and --or --not --all-match
-			"
+		__gitcomp "$__git_grep_options"
 		return
 		;;
 	esac
@@ -1458,11 +1449,15 @@ _git_grep ()
 	__gitcomp_nl "$(__git_refs)"
 }
 
+__git_help_options=
 _git_help ()
 {
+	test -n "$__git_help_options" ||
+	__git_help_options=$(__git_list_command_options help)
+
 	case "$cur" in
 	--*)
-		__gitcomp "--all --info --man --web"
+		__gitcomp "$__git_help_options"
 		return
 		;;
 	esac
@@ -1475,8 +1470,12 @@ _git_help ()
 		"
 }
 
+__git_init_options=
 _git_init ()
 {
+	test -n "$__git_init_options" ||
+	__git_init_options=$(__git_list_command_options init)
+
 	case "$cur" in
 	--shared=*)
 		__gitcomp "
@@ -1485,26 +1484,24 @@ _git_init ()
 		return
 		;;
 	--*)
-		__gitcomp "--quiet --bare --template= --shared --shared="
+		__gitcomp "$__git_init_options"
 		return
 		;;
 	esac
 	COMPREPLY=()
 }
 
+__git_ls_files_options=
 _git_ls_files ()
 {
 	__git_has_doubledash && return
 
+	test -n "$__git_ls_files_options" ||
+	__git_ls_files_options=$(__git_list_command_options ls-files)
+
 	case "$cur" in
 	--*)
-		__gitcomp "--cached --deleted --modified --others --ignored
-			--stage --directory --no-empty-directory --unmerged
-			--killed --exclude= --exclude-from=
-			--exclude-per-directory= --exclude-standard
-			--error-unmatch --with-tree= --full-name
-			--abbrev --ignored --exclude-per-directory
-			"
+		__gitcomp "$__git_ls_files_options"
 		return
 		;;
 	esac
@@ -1516,8 +1513,18 @@ _git_ls_remote ()
 	__gitcomp_nl "$(__git_remotes)"
 }
 
+__git_ls_tree_options=
 _git_ls_tree ()
 {
+	test -n "$__git_ls_tree_options" ||
+	__git_ls_tree_options=$(__git_list_command_options ls-tree)
+
+	case "$cur" in
+	--*)
+		__gitcomp "$__git_ls_tree_options"
+		return
+		;;
+	esac
 	__git_complete_file
 }
 
@@ -1595,14 +1602,17 @@ _git_log ()
 	__git_complete_revlist
 }
 
-__git_merge_options="
-	--no-commit --no-stat --log --no-log --squash --strategy
-	--commit --stat --no-squash --ff --no-ff --ff-only --edit --no-edit
-"
+__git_merge_options=
+__git_compute_merge_options ()
+{
+	test -n "$__git_merge_options" ||
+	__git_merge_options=$(__git_list_command_options merge)
+}
 
 _git_merge ()
 {
 	__git_complete_strategy && return
+	__git_compute_merge_options
 
 	case "$cur" in
 	--*)
@@ -1632,30 +1642,50 @@ _git_merge_base ()
 	__gitcomp_nl "$(__git_refs)"
 }
 
+__git_mv_options=
 _git_mv ()
 {
+	test -n "$__git_mv_options" ||
+	__git_mv_options=$(__git_list_command_options mv)
+
 	case "$cur" in
 	--*)
-		__gitcomp "--dry-run"
+		__gitcomp "$__git_mv_options"
 		return
 		;;
 	esac
 	COMPREPLY=()
 }
 
+__git_name_rev_options=
 _git_name_rev ()
 {
-	__gitcomp "--tags --all --stdin"
+	test -n "$__git_name_rev_options" ||
+	__git_name_rev_options=$(__git_list_command_options name-rev)
+
+	case "$cur" in
+	--*)
+		__gitcomp "$__git_name_rev_options"
+		return
+		;;
+	esac
 }
 
+__git_notes_options=
+__git_notes_add_options=
+__git_notes_copy_options=
+__git_notes_prune_options=
 _git_notes ()
 {
 	local subcommands='add append copy edit list prune remove show'
 	local subcommand="$(__git_find_on_cmdline "$subcommands")"
 
+	test -n "$__git_notes_options" ||
+	__git_notes_options=$(__git_list_command_options notes)
+
 	case "$subcommand,$cur" in
 	,--*)
-		__gitcomp '--ref'
+		__gitcomp "$__git_notes_options"
 		;;
 	,*)
 		case "${words[cword-1]}" in
@@ -1672,14 +1702,19 @@ _git_notes ()
 		__gitcomp_nl "$(__git_refs)" "" "${cur#*=}"
 		;;
 	add,--*|append,--*)
-		__gitcomp '--file= --message= --reedit-message=
-				--reuse-message='
+		test -n "$__git_notes_add_options" ||
+		__git_notes_add_options=$(__git_list_command_options notes add)
+		__gitcomp "$__git_notes_add_options"
 		;;
 	copy,--*)
-		__gitcomp '--stdin'
+		test -n "$__git_notes_copy_options" ||
+		__git_notes_copy_options=$(__git_list_command_options notes copy)
+		__gitcomp "$__git_notes_copy_options"
 		;;
 	prune,--*)
-		__gitcomp '--dry-run --verbose'
+		test -n "$__git_notes_prune_options" ||
+		__git_notes_prune_options=$(__git_list_command_options notes prune)
+		__gitcomp "$__git_notes_prune_options"
 		;;
 	prune,*)
 		;;
@@ -1699,6 +1734,9 @@ _git_pull ()
 {
 	__git_complete_strategy && return
 
+	__git_compute_merge_options
+	__git_compute_fetch_options
+
 	case "$cur" in
 	--*)
 		__gitcomp "
@@ -1712,8 +1750,12 @@ _git_pull ()
 	__git_complete_remote_or_refspec
 }
 
+__git_push_options=
 _git_push ()
 {
+	test -n "$__git_push_options" ||
+	__git_push_options=$(__git_list_command_options push)
+
 	case "$prev" in
 	--repo)
 		__gitcomp_nl "$(__git_remotes)"
@@ -1725,10 +1767,7 @@ _git_push ()
 		return
 		;;
 	--*)
-		__gitcomp "
-			--all --mirror --tags --dry-run --force --verbose
-			--receive-pack= --repo= --set-upstream
-		"
+		__gitcomp "$__git_push_options"
 		return
 		;;
 	esac
@@ -2313,37 +2352,49 @@ _git_replace ()
 	__gitcomp_nl "$(__git_refs)"
 }
 
+__git_reset_options=
 _git_reset ()
 {
 	__git_has_doubledash && return
 
+	test -n "$__git_reset_options" ||
+	__git_reset_options=$(__git_list_command_options reset)
+
 	case "$cur" in
 	--*)
-		__gitcomp "--merge --mixed --hard --soft --patch"
+		__gitcomp "$__git_reset_options"
 		return
 		;;
 	esac
 	__gitcomp_nl "$(__git_refs)"
 }
 
+__git_revert_options=
 _git_revert ()
 {
+	test -n "$__git_revert_options" ||
+	__git_revert_options=$(__git_list_command_options revert)
+
 	case "$cur" in
 	--*)
-		__gitcomp "--edit --mainline --no-edit --no-commit --signoff"
+		__gitcomp "$__git_revert_options"
 		return
 		;;
 	esac
 	__gitcomp_nl "$(__git_refs)"
 }
 
+__git_rm_options=
 _git_rm ()
 {
 	__git_has_doubledash && return
 
+	test -n "$__git_rm_options" ||
+	__git_rm_options=$(__git_list_command_options rm)
+
 	case "$cur" in
 	--*)
-		__gitcomp "--cached --dry-run --ignore-unmatch --quiet"
+		__gitcomp "$__git_rm_options"
 		return
 		;;
 	esac
@@ -2367,10 +2418,14 @@ _git_shortlog ()
 	__git_complete_revlist
 }
 
+__git_show_options=
 _git_show ()
 {
 	__git_has_doubledash && return
 
+	test -n "$__git_show_options" ||
+	__git_show_options=$(__git_list_command_options show)
+
 	case "$cur" in
 	--pretty=*|--format=*)
 		__gitcomp "$__git_log_pretty_formats $(__git_pretty_aliases)
@@ -2378,7 +2433,7 @@ _git_show ()
 		return
 		;;
 	--*)
-		__gitcomp "--pretty= --format= --abbrev-commit --oneline
+		__gitcomp "$__git_show_options
 			$__git_diff_common_options
 			"
 		return
@@ -2387,16 +2442,15 @@ _git_show ()
 	__git_complete_file
 }
 
+__git_show_branch_options=
 _git_show_branch ()
 {
+	test -n "$__git_show_branch_options" ||
+	__git_show_branch_options=$(__git_list_command_options show-branch)
+
 	case "$cur" in
 	--*)
-		__gitcomp "
-			--all --remotes --topo-order --current --more=
-			--list --independent --merge-base --no-name
-			--color --no-color
-			--sha1-name --sparse --topics --reflog
-			"
+		__gitcomp "$__git_show_branch_options"
 		return
 		;;
 	esac
-- 
1.7.10.128.g7945c.dirty

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] parse-options: Add support for dumping out long options
  2012-04-11 10:29 ` [PATCH 1/2] parse-options: Add support for dumping out long options Stephen Boyd
@ 2012-04-11 10:51   ` Felipe Contreras
  2012-04-12  7:42     ` Stephen Boyd
  2012-04-11 12:59   ` Jonathan Nieder
  2012-04-11 14:06   ` SZEDER Gábor
  2 siblings, 1 reply; 14+ messages in thread
From: Felipe Contreras @ 2012-04-11 10:51 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: git, spearce, szeder, jrnieder

On Wed, Apr 11, 2012 at 1:29 PM, Stephen Boyd <bebarino@gmail.com> wrote:
> The bash completion script wants to know what the long options are for a
> certain command at runtime. Add a magical long option that nobody could
> possibly ever use (--dump-raw-long-options) to get this information.

I thought about doing this, but I would like more than just dumping
the options. In zsh one can show more than just the options; each
option can have a description.

I was thinking on something like 'git help --raw'. We also need
something like that to list all the plumbing commands, and options for
certain options, like merge strategies, and so on. Perhaps it would
even make sense to have a new 'git raw-help' command.

Cheers.

-- 
Felipe Contreras

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] parse-options: Add support for dumping out long options
  2012-04-11 10:29 ` [PATCH 1/2] parse-options: Add support for dumping out long options Stephen Boyd
  2012-04-11 10:51   ` Felipe Contreras
@ 2012-04-11 12:59   ` Jonathan Nieder
  2012-04-12  7:02     ` Stephen Boyd
  2012-04-11 14:06   ` SZEDER Gábor
  2 siblings, 1 reply; 14+ messages in thread
From: Jonathan Nieder @ 2012-04-11 12:59 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: git, spearce, szeder, felipe.contreras

Stephen Boyd wrote:

> The bash completion script wants to know what the long options are for a
> certain command at runtime. Add a magical long option that nobody could
> possibly ever use (--dump-raw-long-options) to get this information.

Neat.  Probably should be documented:

diff --git i/Documentation/gitcli.txt w/Documentation/gitcli.txt
index f734f97b..0de074ec 100644
--- i/Documentation/gitcli.txt
+++ w/Documentation/gitcli.txt
@@ -96,6 +96,11 @@ usage: git describe [options] <committish>*
 	are deprecated, and such options are hidden from the default usage. This
 	option gives the full list of options.
 
+--dump-raw-long-options::
+	prints a space-separated list of supported options, including
+	negated `--no-<foo>` forms.  Long options taking an argument are
+	printed with a trailing equal sign, as in "`--depth=`".
+
 
 Negating options
 ~~~~~~~~~~~~~~~~

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/2] completion: Use parse-options raw output for simple long options
  2012-04-11 10:29 ` [PATCH 2/2] completion: Use parse-options raw output for simple " Stephen Boyd
@ 2012-04-11 13:09   ` Jonathan Nieder
  2012-04-11 13:56   ` SZEDER Gábor
  2012-04-17 10:44   ` SZEDER Gábor
  2 siblings, 0 replies; 14+ messages in thread
From: Jonathan Nieder @ 2012-04-11 13:09 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: git, spearce, szeder, felipe.contreras

Stephen Boyd wrote:

> Is there some way to compute these lists with some magical function instead
> of duplicating that logic over and over?

Maybe roughly like this.

	for command in $porcelain
	do
		eval "__git_${command//-/_}_options="
	done
	__git_complete_for_command ()
	{
		local options
		local options_var="__git_${command//-/_}_options"

		eval "options=\$$options_var"
		if test -z "$options"
		then
			eval "$options_var=\$(__git_list_command_options \$command)"
			eval "options=\$$options_var"
		fi

		...
	}

	_git () {
		...
		__git_complete_for_command "$command"
	}

Jonathan

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/2] completion: Use parse-options raw output for simple long options
  2012-04-11 10:29 ` [PATCH 2/2] completion: Use parse-options raw output for simple " Stephen Boyd
  2012-04-11 13:09   ` Jonathan Nieder
@ 2012-04-11 13:56   ` SZEDER Gábor
  2012-04-17 10:44   ` SZEDER Gábor
  2 siblings, 0 replies; 14+ messages in thread
From: SZEDER Gábor @ 2012-04-11 13:56 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: git, spearce, szeder, felipe.contreras, jrnieder

Hi,


On Wed, Apr 11, 2012 at 03:29:25AM -0700, Stephen Boyd wrote:
> Now that parse-options supports generating lists of long options for any
> parse-optified git program we can remove the hand-coded lists in the
> completion script. Replace these lists with code to generate the lists
> lazily when a user tab completes that specific command. Unforunately,
> doing lazy evalution takes more lines than before, but the benefit is we
> reduce the amount of trivial patches to update the script for new and/or
> removed options. It also mildly encourages the migration of git commands
> to the parse-options API.
> 
> Signed-off-by: Stephen Boyd <bebarino@gmail.com>
> ---
> 
> Is there some way to compute these lists with some magical function instead
> of duplicating that logic over and over?

Maybe a function like this:

__git_compute_command_options ()
{
        local varname="__git_${@//[ -]/_}_options"
        eval "test -n \"\$$varname\" || $varname=\"$(git $@ --dump-raw-long-options)\""
}

And then in each completion function just need to call this function
with the command (and possibly subcommand) as parameter:

__git_compute_command_options add


Best,
Gábor

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] parse-options: Add support for dumping out long options
  2012-04-11 10:29 ` [PATCH 1/2] parse-options: Add support for dumping out long options Stephen Boyd
  2012-04-11 10:51   ` Felipe Contreras
  2012-04-11 12:59   ` Jonathan Nieder
@ 2012-04-11 14:06   ` SZEDER Gábor
  2012-04-12  7:12     ` Stephen Boyd
  2 siblings, 1 reply; 14+ messages in thread
From: SZEDER Gábor @ 2012-04-11 14:06 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: git, spearce, felipe.contreras, jrnieder

Hi,


On Wed, Apr 11, 2012 at 03:29:24AM -0700, Stephen Boyd wrote:
> The bash completion script wants to know what the long options are for a
> certain command at runtime. Add a magical long option that nobody could
> possibly ever use (--dump-raw-long-options) to get this information.
> 
> Some example output:
> 
>  $ git clone --dump-raw-long-options
>  --no-verbose --no-quiet --progress --no-progress --no-checkout
>  --checkout --bare --no-bare --mirror --no-mirror --local --no-local
>  --no-hardlinks --hardlinks --shared --no-shared --recursive
>  --no-recursive --recurse-submodules --no-recurse-submodules --template=
>  --no-template --reference= --no-reference --origin= --no-origin
>  --branch= --no-branch --upload-pack= --no-upload-pack --depth=
>  --no-depth --single-branch --no-single-branch --separate-git-dir=
>  --no-separate-git-dir --config= --no-config
> 

I think this is a good idea; there are many completion functions that
fell behind and lack an option or two.

However, in the completion script we deliberately miss options like
'--force', but with your series such options will be offered, too.


Best,
Gábor

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] parse-options: Add support for dumping out long options
  2012-04-11 12:59   ` Jonathan Nieder
@ 2012-04-12  7:02     ` Stephen Boyd
  0 siblings, 0 replies; 14+ messages in thread
From: Stephen Boyd @ 2012-04-12  7:02 UTC (permalink / raw)
  To: Jonathan Nieder; +Cc: git, spearce, szeder, felipe.contreras

On 04/11/2012 05:59 AM, Jonathan Nieder wrote:
> Stephen Boyd wrote:
> 
>> The bash completion script wants to know what the long options are for a
>> certain command at runtime. Add a magical long option that nobody could
>> possibly ever use (--dump-raw-long-options) to get this information.
> 
> Neat.  Probably should be documented:
> 
> diff --git i/Documentation/gitcli.txt w/Documentation/gitcli.txt
> index f734f97b..0de074ec 100644
> --- i/Documentation/gitcli.txt
> +++ w/Documentation/gitcli.txt
> @@ -96,6 +96,11 @@ usage: git describe [options] <committish>*
>  	are deprecated, and such options are hidden from the default usage. This
>  	option gives the full list of options.
>  
> +--dump-raw-long-options::
> +	prints a space-separated list of supported options, including
> +	negated `--no-<foo>` forms.  Long options taking an argument are
> +	printed with a trailing equal sign, as in "`--depth=`".
> +
>  
>  Negating options
>  ~~~~~~~~~~~~~~~~

Thanks. Squashed in.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] parse-options: Add support for dumping out long options
  2012-04-11 14:06   ` SZEDER Gábor
@ 2012-04-12  7:12     ` Stephen Boyd
  2012-04-15 12:49       ` SZEDER Gábor
  0 siblings, 1 reply; 14+ messages in thread
From: Stephen Boyd @ 2012-04-12  7:12 UTC (permalink / raw)
  To: SZEDER Gábor; +Cc: git, spearce, felipe.contreras, jrnieder

On 04/11/2012 07:06 AM, SZEDER Gábor wrote:
> On Wed, Apr 11, 2012 at 03:29:24AM -0700, Stephen Boyd wrote:
>> The bash completion script wants to know what the long options are for a
>> certain command at runtime. Add a magical long option that nobody could
>> possibly ever use (--dump-raw-long-options) to get this information.
>>
>> Some example output:
>>
>>  $ git clone --dump-raw-long-options
>>  --no-verbose --no-quiet --progress --no-progress --no-checkout
>>  --checkout --bare --no-bare --mirror --no-mirror --local --no-local
>>  --no-hardlinks --hardlinks --shared --no-shared --recursive
>>  --no-recursive --recurse-submodules --no-recurse-submodules --template=
>>  --no-template --reference= --no-reference --origin= --no-origin
>>  --branch= --no-branch --upload-pack= --no-upload-pack --depth=
>>  --no-depth --single-branch --no-single-branch --separate-git-dir=
>>  --no-separate-git-dir --config= --no-config
>>
> 
> I think this is a good idea; there are many completion functions that
> fell behind and lack an option or two.
> 
> However, in the completion script we deliberately miss options like
> '--force', but with your series such options will be offered, too.
> 

Hm.. I meant to say something about that in the commit text. I'm willing
to live with wading through some more options when I tab complete if it
means the script never falls out of date with my git installation.

I can envision us putting more smarts into the parse options code to
hide certain options from the raw dump but I'm not sure how useful that
is. Do we need that?

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] parse-options: Add support for dumping out long options
  2012-04-11 10:51   ` Felipe Contreras
@ 2012-04-12  7:42     ` Stephen Boyd
  0 siblings, 0 replies; 14+ messages in thread
From: Stephen Boyd @ 2012-04-12  7:42 UTC (permalink / raw)
  To: Felipe Contreras; +Cc: git, spearce, szeder, jrnieder

On 04/11/2012 03:51 AM, Felipe Contreras wrote:
> On Wed, Apr 11, 2012 at 1:29 PM, Stephen Boyd <bebarino@gmail.com> wrote:
>> The bash completion script wants to know what the long options are for a
>> certain command at runtime. Add a magical long option that nobody could
>> possibly ever use (--dump-raw-long-options) to get this information.
> 
> I thought about doing this, but I would like more than just dumping
> the options. In zsh one can show more than just the options; each
> option can have a description.

Cool. I don't use zsh but it sounds interesting. Perhaps the magical
long option should grow an optional argument? i.e.

	--dump-raw-long-option=zsh

which would dump the options in a format that zsh would like?

Alternatively, we can make a tiny option description grammar that's
easily parsed. I probably won't have time for this any time soon though.

> 
> I was thinking on something like 'git help --raw'. We also need
> something like that to list all the plumbing commands, and options for
> certain options, like merge strategies, and so on. Perhaps it would
> even make sense to have a new 'git raw-help' command.
> 

I'd like to avoid tying the long option stuff to git help so that other
users of parse-options besides git (perhaps perf?) get the dumping
support for free. Actually it works well for 'git notes <subcommand>'
right now so it probably has to stay tied to each git command. Plus I
think we've covered merge strategies and command lists already so I
don't know how useful 'git help --raw' would be.

I have been pondering ways to get all the possible config keys
dynamically. That would remove a huge list (~2000 lines) in the
completion script that always needs updating. Doing that would probably
require some sort of grep over all the source files and a special key
comparison function to look for (#define CONFIG_MATCH strcmp might
work). Even then I don't know how we would handle color.branch.* and
similar things. Maybe we would just do those by hand.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] parse-options: Add support for dumping out long options
  2012-04-12  7:12     ` Stephen Boyd
@ 2012-04-15 12:49       ` SZEDER Gábor
  2012-04-15 19:23         ` Junio C Hamano
  0 siblings, 1 reply; 14+ messages in thread
From: SZEDER Gábor @ 2012-04-15 12:49 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: git, spearce, felipe.contreras, jrnieder

Hi,


On Thu, Apr 12, 2012 at 12:12:32AM -0700, Stephen Boyd wrote:
> On 04/11/2012 07:06 AM, SZEDER Gábor wrote:
> > On Wed, Apr 11, 2012 at 03:29:24AM -0700, Stephen Boyd wrote:
> >> The bash completion script wants to know what the long options are for a
> >> certain command at runtime. Add a magical long option that nobody could
> >> possibly ever use (--dump-raw-long-options) to get this information.
> >>
> >> Some example output:
> >>
> >>  $ git clone --dump-raw-long-options
> >>  --no-verbose --no-quiet --progress --no-progress --no-checkout
> >>  --checkout --bare --no-bare --mirror --no-mirror --local --no-local
> >>  --no-hardlinks --hardlinks --shared --no-shared --recursive
> >>  --no-recursive --recurse-submodules --no-recurse-submodules --template=
> >>  --no-template --reference= --no-reference --origin= --no-origin
> >>  --branch= --no-branch --upload-pack= --no-upload-pack --depth=
> >>  --no-depth --single-branch --no-single-branch --separate-git-dir=
> >>  --no-separate-git-dir --config= --no-config
> >>
> > 
> > I think this is a good idea; there are many completion functions that
> > fell behind and lack an option or two.
> > 
> > However, in the completion script we deliberately miss options like
> > '--force', but with your series such options will be offered, too.
> > 
> 
> Hm.. I meant to say something about that in the commit text. I'm willing
> to live with wading through some more options when I tab complete if it
> means the script never falls out of date with my git installation.
> 
> I can envision us putting more smarts into the parse options code to
> hide certain options from the raw dump but I'm not sure how useful that
> is. Do we need that?

It's not just about wading through some more options.

Parse options already has the PARSE_OPT_HIDDEN flag to omit an option
from the default usage.  Your patch already respects that option, so
e.g. 'git commit --<TAB>' won't offer '--allow-empty', which is meant
for foreign SCM interface scripts.  This is good.

However, '--force' is different, because it should be shown in the
default usage, but since it's a "dangerous" option it should be use
with great care.  That's the reason the completion script doesn't
offer it for any of the commands.

I'm not sure whether there are any such options besides '--force',
though.  If that is the only one, then maybe this is all we need:


diff --git a/parse-options.c b/parse-options.c
index 6c37497c..1a2b0328 100644
--- a/parse-options.c
+++ b/parse-options.c
@@ -371,6 +371,8 @@ static int parse_options_raw(const struct option *opts)
 			continue;
 		if (!opts->long_name)
 			continue;
+		if (!strcmp(opts->long_name, "force"))
+			continue;
 		switch (opts->type) {
 		case OPTION_BIT:
 		case OPTION_NEGBIT:


Best,
Gábor

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/2] parse-options: Add support for dumping out long options
  2012-04-15 12:49       ` SZEDER Gábor
@ 2012-04-15 19:23         ` Junio C Hamano
  0 siblings, 0 replies; 14+ messages in thread
From: Junio C Hamano @ 2012-04-15 19:23 UTC (permalink / raw)
  To: SZEDER Gábor; +Cc: Stephen Boyd, git, spearce, felipe.contreras, jrnieder

SZEDER Gábor <szeder@ira.uka.de> writes:

> Parse options already has the PARSE_OPT_HIDDEN flag to omit an option
> from the default usage.  Your patch already respects that option, so
> e.g. 'git commit --<TAB>' won't offer '--allow-empty', which is meant
> for foreign SCM interface scripts.  This is good.
>
> However, '--force' is different,...

Don't we have enough bits in PARSE_OPT_* namespace so that we can spare
one for PARSE_OPT_OMIT_FROM_COMPLETION?

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/2] completion: Use parse-options raw output for simple long options
  2012-04-11 10:29 ` [PATCH 2/2] completion: Use parse-options raw output for simple " Stephen Boyd
  2012-04-11 13:09   ` Jonathan Nieder
  2012-04-11 13:56   ` SZEDER Gábor
@ 2012-04-17 10:44   ` SZEDER Gábor
  2 siblings, 0 replies; 14+ messages in thread
From: SZEDER Gábor @ 2012-04-17 10:44 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: git, spearce, felipe.contreras, jrnieder

Hi Stephen,

On Wed, Apr 11, 2012 at 03:29:25AM -0700, Stephen Boyd wrote:
> Now that parse-options supports generating lists of long options for any
> parse-optified git program we can remove the hand-coded lists in the
> completion script. Replace these lists with code to generate the lists
> lazily when a user tab completes that specific command.

> +__git_list_command_options ()
> +{
> +	git $@ --dump-raw-long-options
> +}

Attempting option completion for the first time for commands requiring
a repository to work (e.g. 'add', 'branch', 'checkout', etc.) outside
of a git repository produces a 'fatal: not a git repository' error.
These commands require a repository for '--dump-raw-long-options',
too, otherwise they error out in __git_list_command_options().  So at
least we'll need

  git $@ --dump-raw-long-options 2> /dev/null

to silence that error, but even then the user won't get any options.
Now, I don't think that getting a list of options is that useful at
that point, because the command will error out anyway (except when the
user explicitly specifies the paths to the repo and work tree), but
it's a side effect nonetheless, because it worked before.

Computing the long options for commands not requiring a repository
(e.g. 'clone', 'archive', 'help', etc.) works properly even for the
first time and outside of a repository.


Best,
Gábor

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2012-04-17 10:44 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-04-11 10:29 [PATCH 0/2] Dynamic long options for bash completion Stephen Boyd
2012-04-11 10:29 ` [PATCH 1/2] parse-options: Add support for dumping out long options Stephen Boyd
2012-04-11 10:51   ` Felipe Contreras
2012-04-12  7:42     ` Stephen Boyd
2012-04-11 12:59   ` Jonathan Nieder
2012-04-12  7:02     ` Stephen Boyd
2012-04-11 14:06   ` SZEDER Gábor
2012-04-12  7:12     ` Stephen Boyd
2012-04-15 12:49       ` SZEDER Gábor
2012-04-15 19:23         ` Junio C Hamano
2012-04-11 10:29 ` [PATCH 2/2] completion: Use parse-options raw output for simple " Stephen Boyd
2012-04-11 13:09   ` Jonathan Nieder
2012-04-11 13:56   ` SZEDER Gábor
2012-04-17 10:44   ` SZEDER Gábor

Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).