git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [FYI PATCH] git wrapper: DWIM mistyped commands
@ 2008-07-22 20:01 Johannes Schindelin
  2008-07-22 20:16 ` [SCNR] " Pierre Habouzit
                   ` (2 more replies)
  0 siblings, 3 replies; 26+ messages in thread
From: Johannes Schindelin @ 2008-07-22 20:01 UTC (permalink / raw)
  To: git


This patch introduces a modified Damerau-Levenshtein algorithm into
Git's code base, and uses it with the following penalties to show some
similar commands when an unknown command was encountered:

	swap = 0, insertion = 1, substitution = 2, deletion = 4

A typical output would now look like this:

	$ git sm
	git: 'sm' is not a git-command. See 'git --help'.

	Did you mean one of these?
		am
		rm

The cut-off is at similarity rating 6, which was empirically determined
to give sensible results.

As a convenience, if there is only one candidate, Git continues under
the assumption that the user mistyped it.  Example:

	$ git reabse
	WARNING: You called a Git program named 'reabse', which does
	not exist.
	Continuing under the assumption that you meant 'rebase'
	[...]

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---

	So I mistyped 'reabse' for the hundred trillionth time, but I
	will never have to correct my mistakes again.

	Note: this patch is _not_ meant for inclusion.

 Makefile      |    2 +
 builtin.h     |    2 +-
 git.c         |    4 ++-
 help.c        |   61 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 levenshtein.c |   47 +++++++++++++++++++++++++++++++++++++++++++
 levenshtein.h |    8 +++++++
 6 files changed, 121 insertions(+), 3 deletions(-)
 create mode 100644 levenshtein.c
 create mode 100644 levenshtein.h

diff --git a/Makefile b/Makefile
index 19bdd03..7e114e0 100644
--- a/Makefile
+++ b/Makefile
@@ -347,6 +347,7 @@ LIB_H += git-compat-util.h
 LIB_H += graph.h
 LIB_H += grep.h
 LIB_H += hash.h
+LIB_H += levenshtein.h
 LIB_H += list-objects.h
 LIB_H += ll-merge.h
 LIB_H += log-tree.h
@@ -421,6 +422,7 @@ LIB_OBJS += hash.o
 LIB_OBJS += help.o
 LIB_OBJS += ident.o
 LIB_OBJS += interpolate.o
+LIB_OBJS += levenshtein.o
 LIB_OBJS += list-objects.o
 LIB_OBJS += ll-merge.o
 LIB_OBJS += lockfile.o
diff --git a/builtin.h b/builtin.h
index 0e605d4..fc5f108 100644
--- a/builtin.h
+++ b/builtin.h
@@ -11,7 +11,7 @@ extern const char git_usage_string[];
 extern const char git_more_info_string[];
 
 extern void list_common_cmds_help(void);
-extern void help_unknown_cmd(const char *cmd);
+extern const char *help_unknown_cmd(const char *cmd);
 extern void prune_packed_objects(int);
 extern int read_line_with_nul(char *buf, int size, FILE *file);
 extern int fmt_merge_msg(int merge_summary, struct strbuf *in,
diff --git a/git.c b/git.c
index 1bfd271..d7510ef 100644
--- a/git.c
+++ b/git.c
@@ -500,7 +500,9 @@ int main(int argc, const char **argv)
 				cmd, argv[0]);
 			exit(1);
 		}
-		help_unknown_cmd(cmd);
+		argv[0] = help_unknown_cmd(cmd);
+		handle_internal_command(argc, argv);
+		execv_dashed_external(argv);
 	}
 
 	fprintf(stderr, "Failed to run command '%s': %s\n",
diff --git a/help.c b/help.c
index bfc84ae..480befe 100644
--- a/help.c
+++ b/help.c
@@ -9,6 +9,7 @@
 #include "common-cmds.h"
 #include "parse-options.h"
 #include "run-command.h"
+#include "levenshtein.h"
 
 static struct man_viewer_list {
 	struct man_viewer_list *next;
@@ -666,9 +667,67 @@ static void show_html_page(const char *git_cmd)
 	open_html(page_path.buf);
 }
 
-void help_unknown_cmd(const char *cmd)
+static const char *levenshtein_cmd;
+static int similarity(const char *cmd) {
+	return levenshtein(levenshtein_cmd, cmd, 0, 2, 1, 4);
+}
+
+static int levenshtein_compare(const void *p1, const void *p2)
+{
+	const struct cmdname *const *c1 = p1, *const *c2 = p2;
+	const char *s1 = (*c1)->name, *s2 = (*c2)->name;
+	int l1 = similarity(s1);
+	int l2 = similarity(s2);
+	return l1 != l2 ? l1 - l2 : strcmp(s1, s2);
+}
+
+const char *help_unknown_cmd(const char *cmd)
 {
+	int i, best_similarity = 0;
+	char cwd[PATH_MAX];
+
+	if (!getcwd(cwd, sizeof(cwd))) {
+		error("Could not get current working directory");
+		cwd[0] = '\0';
+	}
+
+	load_command_list();
+	ALLOC_GROW(main_cmds.names, main_cmds.cnt + other_cmds.cnt,
+			main_cmds.alloc);
+	memcpy(main_cmds.names + main_cmds.cnt, other_cmds.names,
+		other_cmds.cnt * sizeof(other_cmds.names[0]));
+	main_cmds.cnt += other_cmds.cnt;
+
+	levenshtein_cmd = cmd;
+	qsort(main_cmds.names, main_cmds.cnt,
+	      sizeof(*main_cmds.names), levenshtein_compare);
+
+	if (!main_cmds.cnt)
+		die ("Uh oh.  Your system reports no Git commands at all.");
+	best_similarity = similarity(main_cmds.names[0]->name);
+	if (main_cmds.cnt < 2 || best_similarity <
+			similarity(main_cmds.names[1]->name)) {
+		if (!*cwd)
+			exit(1);
+		if (chdir(cwd))
+			die ("Could not change directory back to '%s'", cwd);
+		fprintf(stderr, "WARNING: You called a Git program named '%s', "
+			"which does not exist.\n"
+			"Continuing under the assumption that you meant '%s'\n",
+			cmd, main_cmds.names[0]->name);
+		return main_cmds.names[0]->name;
+	}
+
 	fprintf(stderr, "git: '%s' is not a git-command. See 'git --help'.\n", cmd);
+
+	if (best_similarity < 6) {
+		fprintf(stderr, "\nDid you mean one of these?\n");
+
+		for (i = 0; i < main_cmds.cnt && best_similarity ==
+				similarity(main_cmds.names[i]->name); i++)
+			fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
+	}
+
 	exit(1);
 }
 
diff --git a/levenshtein.c b/levenshtein.c
new file mode 100644
index 0000000..db52f2c
--- /dev/null
+++ b/levenshtein.c
@@ -0,0 +1,47 @@
+#include "cache.h"
+#include "levenshtein.h"
+
+int levenshtein(const char *string1, const char *string2,
+		int w, int s, int a, int d)
+{
+	int len1 = strlen(string1), len2 = strlen(string2);
+	int *row0 = xmalloc(sizeof(int) * (len2 + 1));
+	int *row1 = xmalloc(sizeof(int) * (len2 + 1));
+	int *row2 = xmalloc(sizeof(int) * (len2 + 1));
+	int i, j;
+
+	for (j = 0; j <= len2; j++)
+		row1[j] = j * a;
+	for (i = 0; i < len1; i++) {
+		int *dummy;
+
+		row2[0] = (i + 1) * d;
+		for (j = 0; j < len2; j++) {
+			/* substitution */
+			row2[j + 1] = row1[j] + s * (string1[i] != string2[j]);
+			/* swap */
+			if (i > 0 && j > 0 && string1[i - 1] == string2[j] &&
+					string1[i] == string2[j - 1] &&
+					row2[j + 1] > row0[j - 1] + w)
+				row2[j + 1] = row0[j - 1] + w;
+			/* deletion */
+			if (j + 1 < len2 && row2[j + 1] > row1[j + 1] + d)
+				row2[j + 1] = row1[j + 1] + d;
+			/* insertion */
+			if (row2[j + 1] > row2[j] + a)
+				row2[j + 1] = row2[j] + a;
+		}
+
+		dummy = row0;
+		row0 = row1;
+		row1 = row2;
+		row2 = dummy;
+	}
+
+	i = row1[len2];
+	free(row0);
+	free(row1);
+	free(row2);
+
+	return i;
+}
diff --git a/levenshtein.h b/levenshtein.h
new file mode 100644
index 0000000..0173abe
--- /dev/null
+++ b/levenshtein.h
@@ -0,0 +1,8 @@
+#ifndef LEVENSHTEIN_H
+#define LEVENSHTEIN_H
+
+int levenshtein(const char *string1, const char *string2,
+	int swap_penalty, int substition_penalty,
+	int insertion_penalty, int deletion_penalty);
+
+#endif
-- 
1.6.0.rc0.21.g91175

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

* [SCNR] Re: [FYI PATCH] git wrapper: DWIM mistyped commands
  2008-07-22 20:01 [FYI PATCH] git wrapper: DWIM mistyped commands Johannes Schindelin
@ 2008-07-22 20:16 ` Pierre Habouzit
  2008-07-22 20:19   ` Johannes Schindelin
  2008-07-22 20:37 ` Alex Riesen
  2008-07-22 23:05 ` [FYI PATCH] git wrapper: DWIM mistyped commands Junio C Hamano
  2 siblings, 1 reply; 26+ messages in thread
From: Pierre Habouzit @ 2008-07-22 20:16 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git

[-- Attachment #1: Type: text/plain, Size: 1627 bytes --]

On Tue, Jul 22, 2008 at 08:01:29PM +0000, Johannes Schindelin wrote:
> 
> This patch introduces a modified Damerau-Levenshtein algorithm into
> Git's code base, and uses it with the following penalties to show some
> similar commands when an unknown command was encountered:
> 
> 	swap = 0, insertion = 1, substitution = 2, deletion = 4
> 
> A typical output would now look like this:
> 
> 	$ git sm
> 	git: 'sm' is not a git-command. See 'git --help'.
> 
> 	Did you mean one of these?
> 		am
> 		rm
> 
> The cut-off is at similarity rating 6, which was empirically determined
> to give sensible results.
> 
> As a convenience, if there is only one candidate, Git continues under
> the assumption that the user mistyped it.  Example:
> 
> 	$ git reabse
> 	WARNING: You called a Git program named 'reabse', which does
> 	not exist.
> 	Continuing under the assumption that you meant 'rebase'
> 	[...]

<SCNR>
    Or use a decent shell:

    When typing e.g.: git tsa<tab>, it yields:
    $ git status
    ---- corrections (errors 1)
    status        -- show working-tree's status
    tag           -- create tag object signed with GPG
    tar-tree      -- create tar archive of the files in the named tree
    ---- original
    tsa

    and it even works for non git commands ;)
</SCNR>

Despite that, I really like your idea. **hint hint** One could even hook that
for long options into parse-options.

-- 
·O·  Pierre Habouzit
··O                                                madcoder@debian.org
OOO                                                http://www.madism.org

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [SCNR] Re: [FYI PATCH] git wrapper: DWIM mistyped commands
  2008-07-22 20:16 ` [SCNR] " Pierre Habouzit
@ 2008-07-22 20:19   ` Johannes Schindelin
  2008-07-22 20:34     ` Pierre Habouzit
  0 siblings, 1 reply; 26+ messages in thread
From: Johannes Schindelin @ 2008-07-22 20:19 UTC (permalink / raw)
  To: Pierre Habouzit; +Cc: git

Hi,

On Tue, 22 Jul 2008, Pierre Habouzit wrote:

> <SCNR>
>     Or use a decent shell:

I tried that:

	git reab<tab><tab><TAB><TTAAABBB!>

> Despite that, I really like your idea. **hint hint**

I said that _I_ did not mean it for inclusion.  **hint hint**

Ciao,
Dscho

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

* Re: [SCNR] Re: [FYI PATCH] git wrapper: DWIM mistyped commands
  2008-07-22 20:19   ` Johannes Schindelin
@ 2008-07-22 20:34     ` Pierre Habouzit
  0 siblings, 0 replies; 26+ messages in thread
From: Pierre Habouzit @ 2008-07-22 20:34 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git

[-- Attachment #1: Type: text/plain, Size: 934 bytes --]

On Tue, Jul 22, 2008 at 08:19:13PM +0000, Johannes Schindelin wrote:
> Hi,
> 
> On Tue, 22 Jul 2008, Pierre Habouzit wrote:
> 
> > <SCNR>
> >     Or use a decent shell:
> 
> I tried that:
> 
> 	git reab<tab><tab><TAB><TTAAABBB!>

It yields the following here:

    $ git read-tree
    ---- corrections (errors 1)
    read-tree  -- read tree information into the directory index
    rebase     -- rebase local commits to new upstream head
    ---- original
    reab

and indeed, it should really suggest rebase first, I suppose I should reorder
my zsh completion error weights. but oh well...

> > Despite that, I really like your idea. **hint hint**
> 
> I said that _I_ did not mean it for inclusion.  **hint hint**

Damn...

-- 
·O·  Pierre Habouzit
··O                                                madcoder@debian.org
OOO                                                http://www.madism.org

[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]

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

* Re: [FYI PATCH] git wrapper: DWIM mistyped commands
  2008-07-22 20:01 [FYI PATCH] git wrapper: DWIM mistyped commands Johannes Schindelin
  2008-07-22 20:16 ` [SCNR] " Pierre Habouzit
@ 2008-07-22 20:37 ` Alex Riesen
  2008-07-22 21:03   ` [PATCH] Add help.autocorrect to enable/disable autocorrecting Alex Riesen
  2008-07-22 23:05 ` [FYI PATCH] git wrapper: DWIM mistyped commands Junio C Hamano
  2 siblings, 1 reply; 26+ messages in thread
From: Alex Riesen @ 2008-07-22 20:37 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git

Johannes Schindelin, Tue, Jul 22, 2008 22:01:29 +0200:
> As a convenience, if there is only one candidate, Git continues under
> the assumption that the user mistyped it.  Example:
> 
> 	$ git reabse
> 	WARNING: You called a Git program named 'reabse', which does
> 	not exist.
> 	Continuing under the assumption that you meant 'rebase'
> 	[...]

Oh, that would make me suspicios (and I hit Ctrl-C fast when I get
suspicios about what happens to my precious data). Could it be
configurable? For example, BASH's cdspell is configurable and even off
by default.

P.S. I'm still using your first patch and am forced to like it every day :)

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

* [PATCH] Add help.autocorrect to enable/disable autocorrecting
  2008-07-22 20:37 ` Alex Riesen
@ 2008-07-22 21:03   ` Alex Riesen
  2008-07-22 21:08     ` Johannes Schindelin
  0 siblings, 1 reply; 26+ messages in thread
From: Alex Riesen @ 2008-07-22 21:03 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git

It is off by default, to avoid scaring people unless they asked to.

---

Alex Riesen, Tue, Jul 22, 2008 22:37:30 +0200:
> Johannes Schindelin, Tue, Jul 22, 2008 22:01:29 +0200:
> > As a convenience, if there is only one candidate, Git continues under
> > the assumption that the user mistyped it.  Example:
> > 
> > 	$ git reabse
> > 	WARNING: You called a Git program named 'reabse', which does
> > 	not exist.
> > 	Continuing under the assumption that you meant 'rebase'
> > 	[...]
> 
> Oh, that would make me suspicios (and I hit Ctrl-C fast when I get
> suspicios about what happens to my precious data). Could it be
> configurable? For example, BASH's cdspell is configurable and even off
> by default.
> 

Like this, perhaps?

 help.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/help.c b/help.c
index 480befe..f08eb9d 100644
--- a/help.c
+++ b/help.c
@@ -28,6 +28,7 @@ enum help_format {
 	HELP_FORMAT_WEB,
 };
 
+static int autocorrect;
 static int show_all = 0;
 static enum help_format help_format = HELP_FORMAT_MAN;
 static struct option builtin_help_options[] = {
@@ -269,6 +270,8 @@ static int git_help_config(const char *var, const char *value, void *cb)
 	}
 	if (!prefixcmp(var, "man."))
 		return add_man_viewer_info(var, value);
+	if (!strcmp(var, "help.autocorrect"))
+		autocorrect = git_config_bool(var,value);
 
 	return git_default_config(var, value, cb);
 }
@@ -704,9 +707,10 @@ const char *help_unknown_cmd(const char *cmd)
 
 	if (!main_cmds.cnt)
 		die ("Uh oh.  Your system reports no Git commands at all.");
+	git_config(git_help_config, NULL);
 	best_similarity = similarity(main_cmds.names[0]->name);
-	if (main_cmds.cnt < 2 || best_similarity <
-			similarity(main_cmds.names[1]->name)) {
+	if (autocorrect && (main_cmds.cnt < 2 ||
+		best_similarity < similarity(main_cmds.names[1]->name))) {
 		if (!*cwd)
 			exit(1);
 		if (chdir(cwd))
-- 
1.6.0.rc0.48.g6dda.dirty

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

* Re: [PATCH] Add help.autocorrect to enable/disable autocorrecting
  2008-07-22 21:03   ` [PATCH] Add help.autocorrect to enable/disable autocorrecting Alex Riesen
@ 2008-07-22 21:08     ` Johannes Schindelin
  2008-07-22 21:26       ` Alex Riesen
  0 siblings, 1 reply; 26+ messages in thread
From: Johannes Schindelin @ 2008-07-22 21:08 UTC (permalink / raw)
  To: Alex Riesen; +Cc: git

Hi,

On Tue, 22 Jul 2008, Alex Riesen wrote:

> +	if (autocorrect && (main_cmds.cnt < 2 ||
> +		best_similarity < similarity(main_cmds.names[1]->name))) {
>  		if (!*cwd)
>  			exit(1);
>  		if (chdir(cwd))

In that case, you need to put in the "one of these" / "this" conditional 
again, which I ripped out because I do not need it any more.

Ciao,
Dscho

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

* [PATCH] Add help.autocorrect to enable/disable autocorrecting
  2008-07-22 21:08     ` Johannes Schindelin
@ 2008-07-22 21:26       ` Alex Riesen
  2008-07-22 21:44         ` Johannes Schindelin
  0 siblings, 1 reply; 26+ messages in thread
From: Alex Riesen @ 2008-07-22 21:26 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git

It is off by default, to avoid scaring people unless they asked to.
---
Johannes Schindelin, Tue, Jul 22, 2008 23:08:19 +0200:
> On Tue, 22 Jul 2008, Alex Riesen wrote:
> 
> > +	if (autocorrect && (main_cmds.cnt < 2 ||
> > +		best_similarity < similarity(main_cmds.names[1]->name))) {
> >  		if (!*cwd)
> >  			exit(1);
> >  		if (chdir(cwd))
> 
> In that case, you need to put in the "one of these" / "this" conditional 
> again, which I ripped out because I do not need it any more.
> 

Of course, missed it. Like this, then.

 help.c |   20 ++++++++++++++------
 1 files changed, 14 insertions(+), 6 deletions(-)

diff --git a/help.c b/help.c
index 480befe..cf6b459 100644
--- a/help.c
+++ b/help.c
@@ -28,6 +28,7 @@ enum help_format {
 	HELP_FORMAT_WEB,
 };
 
+static int autocorrect;
 static int show_all = 0;
 static enum help_format help_format = HELP_FORMAT_MAN;
 static struct option builtin_help_options[] = {
@@ -269,6 +270,8 @@ static int git_help_config(const char *var, const char *value, void *cb)
 	}
 	if (!prefixcmp(var, "man."))
 		return add_man_viewer_info(var, value);
+	if (!strcmp(var, "help.autocorrect"))
+		autocorrect = git_config_bool(var,value);
 
 	return git_default_config(var, value, cb);
 }
@@ -704,9 +707,10 @@ const char *help_unknown_cmd(const char *cmd)
 
 	if (!main_cmds.cnt)
 		die ("Uh oh.  Your system reports no Git commands at all.");
+	git_config(git_help_config, NULL);
 	best_similarity = similarity(main_cmds.names[0]->name);
-	if (main_cmds.cnt < 2 || best_similarity <
-			similarity(main_cmds.names[1]->name)) {
+	if (autocorrect && (main_cmds.cnt < 2 ||
+		best_similarity < similarity(main_cmds.names[1]->name))) {
 		if (!*cwd)
 			exit(1);
 		if (chdir(cwd))
@@ -721,10 +725,14 @@ const char *help_unknown_cmd(const char *cmd)
 	fprintf(stderr, "git: '%s' is not a git-command. See 'git --help'.\n", cmd);
 
 	if (best_similarity < 6) {
-		fprintf(stderr, "\nDid you mean one of these?\n");
-
-		for (i = 0; i < main_cmds.cnt && best_similarity ==
-				similarity(main_cmds.names[i]->name); i++)
+		int n = 0;
+		while (n < main_cmds.cnt &&
+			best_similarity == similarity(main_cmds.names[n]->name))
+			++n;
+		fprintf(stderr, "\nDid you mean %s?\n",
+			n < 2 ? "this": "one of these");
+
+		for (i = 0; i < n; i++)
 			fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
 	}
 
-- 
1.6.0.rc0.48.ga184

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

* Re: [PATCH] Add help.autocorrect to enable/disable autocorrecting
  2008-07-22 21:26       ` Alex Riesen
@ 2008-07-22 21:44         ` Johannes Schindelin
  2008-07-22 22:25           ` Alex Riesen
  2008-07-22 23:08           ` Junio C Hamano
  0 siblings, 2 replies; 26+ messages in thread
From: Johannes Schindelin @ 2008-07-22 21:44 UTC (permalink / raw)
  To: Alex Riesen; +Cc: git

Hi,

On Tue, 22 Jul 2008, Alex Riesen wrote:

> @@ -704,9 +707,10 @@ const char *help_unknown_cmd(const char *cmd)
>  
>  	if (!main_cmds.cnt)
>  		die ("Uh oh.  Your system reports no Git commands at all.");
> +	git_config(git_help_config, NULL);
>  	best_similarity = similarity(main_cmds.names[0]->name);
> -	if (main_cmds.cnt < 2 || best_similarity <
> -			similarity(main_cmds.names[1]->name)) {
> +	if (autocorrect && (main_cmds.cnt < 2 ||
> +		best_similarity < similarity(main_cmds.names[1]->name))) {
>  		if (!*cwd)
>  			exit(1);
>  		if (chdir(cwd))

This "if" already checks if there is only one candidate.  So you should 
just add an inner "if (autocorrect) ... else single = 1;" or some such.

However, I think that the intention of this patch is too much DWIMery, 
which might be good for me (just like my "git add remote" patch), but not 
for the general audience.

Ciao,
Dscho

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

* [PATCH] Add help.autocorrect to enable/disable autocorrecting
  2008-07-22 21:44         ` Johannes Schindelin
@ 2008-07-22 22:25           ` Alex Riesen
  2008-07-23 16:44             ` Johannes Schindelin
  2008-07-22 23:08           ` Junio C Hamano
  1 sibling, 1 reply; 26+ messages in thread
From: Alex Riesen @ 2008-07-22 22:25 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git

It is off by default, to avoid scaring people unless they asked to.
---

Johannes Schindelin, Tue, Jul 22, 2008 23:44:50 +0200:
> On Tue, 22 Jul 2008, Alex Riesen wrote:
> 
> > @@ -704,9 +707,10 @@ const char *help_unknown_cmd(const char *cmd)
> >  
> >  	if (!main_cmds.cnt)
> >  		die ("Uh oh.  Your system reports no Git commands at all.");
> > +	git_config(git_help_config, NULL);
> >  	best_similarity = similarity(main_cmds.names[0]->name);
> > -	if (main_cmds.cnt < 2 || best_similarity <
> > -			similarity(main_cmds.names[1]->name)) {
> > +	if (autocorrect && (main_cmds.cnt < 2 ||
> > +		best_similarity < similarity(main_cmds.names[1]->name))) {
> >  		if (!*cwd)
> >  			exit(1);
> >  		if (chdir(cwd))
> 
> This "if" already checks if there is only one candidate.  So you should 
> just add an inner "if (autocorrect) ... else single = 1;" or some such.

Oh right, stupid me.

> However, I think that the intention of this patch is too much DWIMery, 
> which might be good for me (just like my "git add remote" patch), but not 
> for the general audience.

Mustn't be good for all (for the "general audience" it is even common
practice to forget to thank. It may be even a sign of bad manners for
it). It is good for me though. And thanks for sharing.

Moved git_config before the calls where current directory is changed:
so that it has the same filesystem context as in normal case. Less
surprises.

 help.c |   19 +++++++++++++------
 1 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/help.c b/help.c
index 480befe..8b25a55 100644
--- a/help.c
+++ b/help.c
@@ -28,6 +28,7 @@ enum help_format {
 	HELP_FORMAT_WEB,
 };
 
+static int autocorrect;
 static int show_all = 0;
 static enum help_format help_format = HELP_FORMAT_MAN;
 static struct option builtin_help_options[] = {
@@ -269,6 +270,8 @@ static int git_help_config(const char *var, const char *value, void *cb)
 	}
 	if (!prefixcmp(var, "man."))
 		return add_man_viewer_info(var, value);
+	if (!strcmp(var, "help.autocorrect"))
+		autocorrect = git_config_bool(var,value);
 
 	return git_default_config(var, value, cb);
 }
@@ -683,7 +686,7 @@ static int levenshtein_compare(const void *p1, const void *p2)
 
 const char *help_unknown_cmd(const char *cmd)
 {
-	int i, best_similarity = 0;
+	int i, best_similarity = 0, n;
 	char cwd[PATH_MAX];
 
 	if (!getcwd(cwd, sizeof(cwd))) {
@@ -691,6 +694,7 @@ const char *help_unknown_cmd(const char *cmd)
 		cwd[0] = '\0';
 	}
 
+	git_config(git_help_config, NULL);
 	load_command_list();
 	ALLOC_GROW(main_cmds.names, main_cmds.cnt + other_cmds.cnt,
 			main_cmds.alloc);
@@ -705,8 +709,11 @@ const char *help_unknown_cmd(const char *cmd)
 	if (!main_cmds.cnt)
 		die ("Uh oh.  Your system reports no Git commands at all.");
 	best_similarity = similarity(main_cmds.names[0]->name);
-	if (main_cmds.cnt < 2 || best_similarity <
-			similarity(main_cmds.names[1]->name)) {
+	n = 1;
+	while (n < main_cmds.cnt &&
+		best_similarity == similarity(main_cmds.names[n]->name))
+		++n;
+	if (autocorrect && n == 1) {
 		if (!*cwd)
 			exit(1);
 		if (chdir(cwd))
@@ -721,10 +728,10 @@ const char *help_unknown_cmd(const char *cmd)
 	fprintf(stderr, "git: '%s' is not a git-command. See 'git --help'.\n", cmd);
 
 	if (best_similarity < 6) {
-		fprintf(stderr, "\nDid you mean one of these?\n");
+		fprintf(stderr, "\nDid you mean %s?\n",
+			n < 2 ? "this": "one of these");
 
-		for (i = 0; i < main_cmds.cnt && best_similarity ==
-				similarity(main_cmds.names[i]->name); i++)
+		for (i = 0; i < n; i++)
 			fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
 	}
 
-- 
1.6.0.rc0.48.ga184

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

* Re: [FYI PATCH] git wrapper: DWIM mistyped commands
  2008-07-22 20:01 [FYI PATCH] git wrapper: DWIM mistyped commands Johannes Schindelin
  2008-07-22 20:16 ` [SCNR] " Pierre Habouzit
  2008-07-22 20:37 ` Alex Riesen
@ 2008-07-22 23:05 ` Junio C Hamano
  2008-07-22 23:10   ` Sverre Rabbelier
  2 siblings, 1 reply; 26+ messages in thread
From: Junio C Hamano @ 2008-07-22 23:05 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> 	So I mistyped 'reabse' for the hundred trillionth time, but I
> 	will never have to correct my mistakes again.
>
> 	Note: this patch is _not_ meant for inclusion.

Heh, I do "git emrge" all the time ;-)

Time to start a "gitster private edition" branch for my own use, I guess.

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

* Re: [PATCH] Add help.autocorrect to enable/disable autocorrecting
  2008-07-22 21:44         ` Johannes Schindelin
  2008-07-22 22:25           ` Alex Riesen
@ 2008-07-22 23:08           ` Junio C Hamano
  2008-07-23 16:41             ` [PATCH] Wait help.autocorrect deciseconds before running corrected command Alex Riesen
  1 sibling, 1 reply; 26+ messages in thread
From: Junio C Hamano @ 2008-07-22 23:08 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Alex Riesen, git

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:

> Hi,
>
> On Tue, 22 Jul 2008, Alex Riesen wrote:
>
>> @@ -704,9 +707,10 @@ const char *help_unknown_cmd(const char *cmd)
>>  
>>  	if (!main_cmds.cnt)
>>  		die ("Uh oh.  Your system reports no Git commands at all.");
>> +	git_config(git_help_config, NULL);
>>  	best_similarity = similarity(main_cmds.names[0]->name);
>> -	if (main_cmds.cnt < 2 || best_similarity <
>> -			similarity(main_cmds.names[1]->name)) {
>> +	if (autocorrect && (main_cmds.cnt < 2 ||
>> +		best_similarity < similarity(main_cmds.names[1]->name))) {
>>  		if (!*cwd)
>>  			exit(1);
>>  		if (chdir(cwd))
>
> This "if" already checks if there is only one candidate.  So you should 
> just add an inner "if (autocorrect) ... else single = 1;" or some such.
>
> However, I think that the intention of this patch is too much DWIMery, 
> which might be good for me (just like my "git add remote" patch), but not 
> for the general audience.

Please make autocorrect not a binary but optionally the number of
deciseconds before it continues, so that I have a chance to hit ^C ;-)

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

* Re: [FYI PATCH] git wrapper: DWIM mistyped commands
  2008-07-22 23:05 ` [FYI PATCH] git wrapper: DWIM mistyped commands Junio C Hamano
@ 2008-07-22 23:10   ` Sverre Rabbelier
  0 siblings, 0 replies; 26+ messages in thread
From: Sverre Rabbelier @ 2008-07-22 23:10 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Johannes Schindelin, git

On Wed, Jul 23, 2008 at 1:05 AM, Junio C Hamano <gitster@pobox.com> wrote:
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
>
>>       So I mistyped 'reabse' for the hundred trillionth time, but I
>>       will never have to correct my mistakes again.
>>
>>       Note: this patch is _not_ meant for inclusion.
>
> Heh, I do "git emrge" all the time ;-)
>
> Time to start a "gitster private edition" branch for my own use, I guess.

If it is the same typo all the time, wouldn't aliasses do the trick?

-- 
Cheers,

Sverre Rabbelier

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

* [PATCH] Wait help.autocorrect deciseconds before running corrected command
  2008-07-22 23:08           ` Junio C Hamano
@ 2008-07-23 16:41             ` Alex Riesen
  2008-07-23 16:57               ` Johannes Schindelin
  0 siblings, 1 reply; 26+ messages in thread
From: Alex Riesen @ 2008-07-23 16:41 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: Johannes Schindelin, git

Suggested by Junio, so he has a chance to hit Ctrl-C.
---
Junio C Hamano, Wed, Jul 23, 2008 01:08:17 +0200:
> 
> Please make autocorrect not a binary but optionally the number of
> deciseconds before it continues, so that I have a chance to hit ^C ;-)

on top of the last patch.

 Documentation/config.txt |    9 +++++++++
 help.c                   |    7 ++++++-
 2 files changed, 15 insertions(+), 1 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index e784805..5bf1d0d 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -771,6 +771,15 @@ help.format::
 	Values 'man', 'info', 'web' and 'html' are supported. 'man' is
 	the default. 'web' and 'html' are the same.
 
+help.autocorrect::
+	Automatically correct and execute mistyped commands after
+	waiting for the given number of deciseconds (0.1 sec). If more
+	than one command can be deduced from the entered text, nothing
+	will be executed.  If the value of this option is negative,
+	the corrected command will be executed immediately. If the
+	value is 0 - the command will be just shown but not executed.
+	This is the default.
+
 http.proxy::
 	Override the HTTP proxy, normally configured using the 'http_proxy'
 	environment variable (see linkgit:curl[1]).  This can be overridden
diff --git a/help.c b/help.c
index 8b25a55..4d52781 100644
--- a/help.c
+++ b/help.c
@@ -271,7 +271,7 @@ static int git_help_config(const char *var, const char *value, void *cb)
 	if (!prefixcmp(var, "man."))
 		return add_man_viewer_info(var, value);
 	if (!strcmp(var, "help.autocorrect"))
-		autocorrect = git_config_bool(var,value);
+		autocorrect = git_config_int(var,value);
 
 	return git_default_config(var, value, cb);
 }
@@ -722,6 +722,11 @@ const char *help_unknown_cmd(const char *cmd)
 			"which does not exist.\n"
 			"Continuing under the assumption that you meant '%s'\n",
 			cmd, main_cmds.names[0]->name);
+		if (autocorrect > 0) {
+			fprintf(stderr, "in %0.1f seconds automatically...\n",
+				(float)autocorrect/10.0);
+			poll(NULL, 0, autocorrect * 100);
+		}
 		return main_cmds.names[0]->name;
 	}
 
-- 
1.6.0.rc0.50.g9c23

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

* Re: [PATCH] Add help.autocorrect to enable/disable autocorrecting
  2008-07-22 22:25           ` Alex Riesen
@ 2008-07-23 16:44             ` Johannes Schindelin
  2008-07-23 18:44               ` Alex Riesen
  0 siblings, 1 reply; 26+ messages in thread
From: Johannes Schindelin @ 2008-07-23 16:44 UTC (permalink / raw)
  To: Alex Riesen; +Cc: git

Hi,

On Wed, 23 Jul 2008, Alex Riesen wrote:

> Johannes Schindelin, Tue, Jul 22, 2008 23:44:50 +0200:
> > However, I think that the intention of this patch is too much DWIMery, 
> > which might be good for me (just like my "git add remote" patch), but 
> > not for the general audience.
> 
> Mustn't be good for all

You meant "needn't"?  It is good for me ;-)

> And thanks for sharing.

You're welcome.

> +	n = 1;
> +	while (n < main_cmds.cnt &&
> +		best_similarity == similarity(main_cmds.names[n]->name))
> +		++n;

Mini-nit: you never ask for the value of n, only if it is 1 or larger.  So 
you do not need to count...

Ciao,
Dscho

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

* Re: [PATCH] Wait help.autocorrect deciseconds before running corrected command
  2008-07-23 16:41             ` [PATCH] Wait help.autocorrect deciseconds before running corrected command Alex Riesen
@ 2008-07-23 16:57               ` Johannes Schindelin
  2008-07-23 18:45                 ` Alex Riesen
  0 siblings, 1 reply; 26+ messages in thread
From: Johannes Schindelin @ 2008-07-23 16:57 UTC (permalink / raw)
  To: Alex Riesen; +Cc: Junio C Hamano, git

Hi,

On Wed, 23 Jul 2008, Alex Riesen wrote:

> +		if (autocorrect > 0) {
> +			fprintf(stderr, "in %0.1f seconds automatically...\n",
> +				(float)autocorrect/10.0);
> +			poll(NULL, 0, autocorrect * 100);
> +		}

What?  No countdown?  No fancy sounds when the time ran up?

Ciao,
Dscho

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

* Re: [PATCH] Add help.autocorrect to enable/disable autocorrecting
  2008-07-23 16:44             ` Johannes Schindelin
@ 2008-07-23 18:44               ` Alex Riesen
  2008-07-23 19:00                 ` Johannes Schindelin
  0 siblings, 1 reply; 26+ messages in thread
From: Alex Riesen @ 2008-07-23 18:44 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: git

Johannes Schindelin, Wed, Jul 23, 2008 18:44:49 +0200:
> > +	n = 1;
> > +	while (n < main_cmds.cnt &&
> > +		best_similarity == similarity(main_cmds.names[n]->name))
> > +		++n;
> 
> Mini-nit: you never ask for the value of n, only if it is 1 or larger.  So 
> you do not need to count...

But I do, don't I? AFAICS, I use 0, 1 and >1 (this-these).

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

* Re: [PATCH] Wait help.autocorrect deciseconds before running corrected command
  2008-07-23 16:57               ` Johannes Schindelin
@ 2008-07-23 18:45                 ` Alex Riesen
  0 siblings, 0 replies; 26+ messages in thread
From: Alex Riesen @ 2008-07-23 18:45 UTC (permalink / raw)
  To: Johannes Schindelin; +Cc: Junio C Hamano, git

Johannes Schindelin, Wed, Jul 23, 2008 18:57:05 +0200:
> On Wed, 23 Jul 2008, Alex Riesen wrote:
> 
> > +		if (autocorrect > 0) {
> > +			fprintf(stderr, "in %0.1f seconds automatically...\n",
> > +				(float)autocorrect/10.0);
> > +			poll(NULL, 0, autocorrect * 100);
> > +		}
> 
> What?  No countdown?  No fancy sounds when the time ran up?
> 

Hate them fancies... :)

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

* Re: [PATCH] Add help.autocorrect to enable/disable autocorrecting
  2008-07-23 18:44               ` Alex Riesen
@ 2008-07-23 19:00                 ` Johannes Schindelin
  2008-07-23 19:04                   ` Johannes Schindelin
  0 siblings, 1 reply; 26+ messages in thread
From: Johannes Schindelin @ 2008-07-23 19:00 UTC (permalink / raw)
  To: Alex Riesen; +Cc: git

Hi,

On Wed, 23 Jul 2008, Alex Riesen wrote:

> Johannes Schindelin, Wed, Jul 23, 2008 18:44:49 +0200:
> > > +	n = 1;
> > > +	while (n < main_cmds.cnt &&
> > > +		best_similarity == similarity(main_cmds.names[n]->name))
> > > +		++n;
> > 
> > Mini-nit: you never ask for the value of n, only if it is 1 or larger.  So 
> > you do not need to count...
> 
> But I do, don't I? AFAICS, I use 0, 1 and >1 (this-these).

Yes.  So check cnt > 0 && best_similarity > 5 says if it is 0, and 
cnt > 1 && best_similarity < similarity(...[1]...) says if it is 1.

Ergo: no need to count,
Dscho

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

* Re: [PATCH] Add help.autocorrect to enable/disable autocorrecting
  2008-07-23 19:00                 ` Johannes Schindelin
@ 2008-07-23 19:04                   ` Johannes Schindelin
  0 siblings, 0 replies; 26+ messages in thread
From: Johannes Schindelin @ 2008-07-23 19:04 UTC (permalink / raw)
  To: Alex Riesen; +Cc: git

Hi,

On Wed, 23 Jul 2008, Johannes Schindelin wrote:

> On Wed, 23 Jul 2008, Alex Riesen wrote:
> 
> > Johannes Schindelin, Wed, Jul 23, 2008 18:44:49 +0200:
> > > > +	n = 1;
> > > > +	while (n < main_cmds.cnt &&
> > > > +		best_similarity == similarity(main_cmds.names[n]->name))
> > > > +		++n;
> > > 
> > > Mini-nit: you never ask for the value of n, only if it is 1 or larger.  So 
> > > you do not need to count...
> > 
> > But I do, don't I? AFAICS, I use 0, 1 and >1 (this-these).
> 
> Yes.  So check cnt > 0 && best_similarity > 5 says if it is 0,

Oh, I just realized that my patch is bogus anyway.  It only checks for 
best_similarity > 5 in the case that the first two commands have equal 
similarity.  D'oh.

Ciao,
Dscho

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

* Re: [PATCH] Add help.autocorrect to enable/disable autocorrecting
  2008-08-28 21:28   ` [PATCH] Add help.autocorrect to enable/disable autocorrecting Alex Riesen
  2008-08-29 10:11     ` Andreas Ericsson
@ 2008-09-08  6:50     ` Junio C Hamano
  1 sibling, 0 replies; 26+ messages in thread
From: Junio C Hamano @ 2008-09-08  6:50 UTC (permalink / raw)
  To: Alex Riesen; +Cc: git, Johannes Schindelin

Alex Riesen <raa.lkml@gmail.com> writes:

> It is off(0) by default, to avoid scaring people unless they asked to.

I do not think this is off by default, by the way.  "off by default" means
that you would not waste extra cycles to compute the list of suggestions.

I am not suggesting that it should be "off" by default in that sense,
though.  I am just pointing out that it is not described correctly.

I also noticed that this does not seem to pay attention to mistyped
aliases.  Is it by design, oversight, or lazyness?

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

* Re: [PATCH] Add help.autocorrect to enable/disable autocorrecting
  2008-08-31 14:49               ` Matthieu Moy
@ 2008-08-31 16:33                 ` Junio C Hamano
  0 siblings, 0 replies; 26+ messages in thread
From: Junio C Hamano @ 2008-08-31 16:33 UTC (permalink / raw)
  To: Matthieu Moy; +Cc: Alex Riesen, git, Johannes Schindelin

Matthieu Moy <Matthieu.Moy@imag.fr> writes:

> Alex Riesen <raa.lkml@gmail.com> writes:
>
>> It is off(0) by default, to avoid scaring people unless they asked to.
>> If set to a non-0 value, wait for that amount of deciseconds before
>> running the corrected command.
>
> Perhaps off should be -1 (or, say, anything negative), so that the
> value 0 can be used to mean "execute the corrected command without
> waiting".
>
> (not that I really care personnally, I'd probably keep it off anyway).

I do not want to suggest this because I do not think of a good way to
implement it myself, but it would be very nice if this feature can be
enabled by default for interactive session and disabled for scripts.

Well, actually I think I do ;-)

Perhaps have a bash alias that does:

	alias git="git --dwim"

only in interactive session (ensuring "only in interactive" is the
responsibility of the end user), with the global option similar to
the "--paginate" that "git" wrapper itself takes?

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

* Re: [PATCH] Add help.autocorrect to enable/disable autocorrecting
  2008-08-31 13:54             ` [PATCH] Add help.autocorrect to enable/disable autocorrecting Alex Riesen
@ 2008-08-31 14:49               ` Matthieu Moy
  2008-08-31 16:33                 ` Junio C Hamano
  0 siblings, 1 reply; 26+ messages in thread
From: Matthieu Moy @ 2008-08-31 14:49 UTC (permalink / raw)
  To: Alex Riesen; +Cc: Junio C Hamano, git, Johannes Schindelin

Alex Riesen <raa.lkml@gmail.com> writes:

> It is off(0) by default, to avoid scaring people unless they asked to.
> If set to a non-0 value, wait for that amount of deciseconds before
> running the corrected command.

Perhaps off should be -1 (or, say, anything negative), so that the
value 0 can be used to mean "execute the corrected command without
waiting".

(not that I really care personnally, I'd probably keep it off anyway).

-- 
Matthieu

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

* [PATCH] Add help.autocorrect to enable/disable autocorrecting
  2008-08-31 13:50           ` [PATCH] git wrapper: DWIM mistyped commands Alex Riesen
@ 2008-08-31 13:54             ` Alex Riesen
  2008-08-31 14:49               ` Matthieu Moy
  0 siblings, 1 reply; 26+ messages in thread
From: Alex Riesen @ 2008-08-31 13:54 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git, Johannes Schindelin

It is off(0) by default, to avoid scaring people unless they asked to.
If set to a non-0 value, wait for that amount of deciseconds before
running the corrected command.

Suggested by Junio, so he has a chance to hit Ctrl-C.

Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
---
Alex Riesen, Sun, Aug 31, 2008 15:50:23 +0200:
> Junio C Hamano, Sat, Aug 30, 2008 19:26:17 +0200:
> > Please reroll the whole f66dd34 (git wrapper: DWIM mistyped commands,
> > 2008-08-28), as it is not part of any solid integration branch yet.
> 
> I think I better reroll (now) both
> 

 Documentation/config.txt |    9 +++++++++
 help.c                   |   19 ++++++++++++++++++-
 2 files changed, 27 insertions(+), 1 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index af57d94..8c644ab 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -790,6 +790,15 @@ help.format::
 	Values 'man', 'info', 'web' and 'html' are supported. 'man' is
 	the default. 'web' and 'html' are the same.
 
+help.autocorrect::
+	Automatically correct and execute mistyped commands after
+	waiting for the given number of deciseconds (0.1 sec). If more
+	than one command can be deduced from the entered text, nothing
+	will be executed.  If the value of this option is negative,
+	the corrected command will be executed immediately. If the
+	value is 0 - the command will be just shown but not executed.
+	This is the default.
+
 http.proxy::
 	Override the HTTP proxy, normally configured using the 'http_proxy'
 	environment variable (see linkgit:curl[1]).  This can be overridden
diff --git a/help.c b/help.c
index aaba809..300cd38 100644
--- a/help.c
+++ b/help.c
@@ -261,6 +261,16 @@ int is_in_cmdlist(struct cmdnames *c, const char *s)
 	return 0;
 }
 
+static int autocorrect;
+
+static int git_unknown_cmd_config(const char *var, const char *value, void *cb)
+{
+	if (!strcmp(var, "help.autocorrect"))
+		autocorrect = git_config_int(var,value);
+
+	return git_default_config(var, value, cb);
+}
+
 static int levenshtein_compare(const void *p1, const void *p2)
 {
 	const struct cmdname *const *c1 = p1, *const *c2 = p2;
@@ -278,6 +288,8 @@ const char *help_unknown_cmd(const char *cmd)
 	memset(&main_cmds, 0, sizeof(main_cmds));
 	memset(&other_cmds, 0, sizeof(main_cmds));
 
+	git_config(git_unknown_cmd_config, NULL);
+
 	load_command_list("git-", &main_cmds, &other_cmds);
 
 	ALLOC_GROW(main_cmds.names, main_cmds.cnt + other_cmds.cnt,
@@ -302,7 +314,7 @@ const char *help_unknown_cmd(const char *cmd)
 	n = 1;
 	while (n < main_cmds.cnt && best_similarity == main_cmds.names[n]->len)
 		++n;
-	if (n == 1) {
+	if (autocorrect && n == 1) {
 		const char *assumed = main_cmds.names[0]->name;
 		main_cmds.names[0] = NULL;
 		clean_cmdnames(&main_cmds);
@@ -310,6 +322,11 @@ const char *help_unknown_cmd(const char *cmd)
 			"which does not exist.\n"
 			"Continuing under the assumption that you meant '%s'\n",
 			cmd, assumed);
+		if (autocorrect > 0) {
+			fprintf(stderr, "in %0.1f seconds automatically...\n",
+				(float)autocorrect/10.0);
+			poll(NULL, 0, autocorrect * 100);
+		}
 		return assumed;
 	}
 
-- 
1.6.0.1.168.gdf6f0

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

* Re: [PATCH] Add help.autocorrect to enable/disable autocorrecting
  2008-08-28 21:28   ` [PATCH] Add help.autocorrect to enable/disable autocorrecting Alex Riesen
@ 2008-08-29 10:11     ` Andreas Ericsson
  2008-09-08  6:50     ` Junio C Hamano
  1 sibling, 0 replies; 26+ messages in thread
From: Andreas Ericsson @ 2008-08-29 10:11 UTC (permalink / raw)
  To: Alex Riesen; +Cc: git, Junio C Hamano, Johannes Schindelin

Alex Riesen wrote:
> It is off(0) by default, to avoid scaring people unless they asked to.
> If set to a non-0 value, wait for that amount of deciseconds before
> running the corrected command.
> 
> Suggested by Junio, so he has a chance to hit Ctrl-C.
> 

I'm just plain loving this :)

Liked-by: Andreas Ericsson <ae@op5.se>

-- 
Andreas Ericsson                   andreas.ericsson@op5.se
OP5 AB                             www.op5.se
Tel: +46 8-230225                  Fax: +46 8-230231

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

* [PATCH] Add help.autocorrect to enable/disable autocorrecting
  2008-08-28 21:27 ` [PATCH updated] git wrapper: DWIM mistyped commands Alex Riesen
@ 2008-08-28 21:28   ` Alex Riesen
  2008-08-29 10:11     ` Andreas Ericsson
  2008-09-08  6:50     ` Junio C Hamano
  2008-08-30 15:36   ` [PATCH updated] git wrapper: DWIM mistyped commands Junio C Hamano
  1 sibling, 2 replies; 26+ messages in thread
From: Alex Riesen @ 2008-08-28 21:28 UTC (permalink / raw)
  To: git; +Cc: Junio C Hamano, Johannes Schindelin

It is off(0) by default, to avoid scaring people unless they asked to.
If set to a non-0 value, wait for that amount of deciseconds before
running the corrected command.

Suggested by Junio, so he has a chance to hit Ctrl-C.

Signed-off-by: Alex Riesen <raa.lkml@gmail.com>
---
 Documentation/config.txt |    9 ++++++++
 help.c                   |   50 ++++++++++++++++++++++++++++++++++++++-------
 2 files changed, 51 insertions(+), 8 deletions(-)

diff --git a/Documentation/config.txt b/Documentation/config.txt
index af57d94..8c644ab 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -790,6 +790,15 @@ help.format::
 	Values 'man', 'info', 'web' and 'html' are supported. 'man' is
 	the default. 'web' and 'html' are the same.
 
+help.autocorrect::
+	Automatically correct and execute mistyped commands after
+	waiting for the given number of deciseconds (0.1 sec). If more
+	than one command can be deduced from the entered text, nothing
+	will be executed.  If the value of this option is negative,
+	the corrected command will be executed immediately. If the
+	value is 0 - the command will be just shown but not executed.
+	This is the default.
+
 http.proxy::
 	Override the HTTP proxy, normally configured using the 'http_proxy'
 	environment variable (see linkgit:curl[1]).  This can be overridden
diff --git a/help.c b/help.c
index 981fb02..7bfbbcd 100644
--- a/help.c
+++ b/help.c
@@ -38,6 +38,16 @@ void add_cmdname(struct cmdnames *cmds, const char *name, int len)
 	cmds->names[cmds->cnt++] = ent;
 }
 
+static void clean_cmdnames(struct cmdnames *cmds)
+{
+	int i;
+	for (i = 0; i < cmds->cnt; ++i)
+		free(cmds->names[i]);
+	free(cmds->names);
+	cmds->cnt = 0;
+	cmds->alloc = 0;
+}
+
 static int cmdname_compare(const void *a_, const void *b_)
 {
 	struct cmdname *a = *(struct cmdname **)a_;
@@ -258,6 +268,16 @@ int is_in_cmdlist(struct cmdnames *c, const char *s)
 	return 0;
 }
 
+static int autocorrect;
+
+static int git_unknown_cmd_config(const char *var, const char *value, void *cb)
+{
+	if (!strcmp(var, "help.autocorrect"))
+		autocorrect = git_config_int(var,value);
+
+	return git_default_config(var, value, cb);
+}
+
 static const char *levenshtein_cmd;
 static int similarity(const char *cmd) {
 	return levenshtein(levenshtein_cmd, cmd, 0, 2, 1, 4);
@@ -274,7 +294,7 @@ static int levenshtein_compare(const void *p1, const void *p2)
 
 const char *help_unknown_cmd(const char *cmd)
 {
-	int i, best_similarity = 0;
+	int i, best_similarity = 0, n;
 	char cwd[PATH_MAX];
 	static struct cmdnames main_cmds, other_cmds;
 
@@ -283,6 +303,7 @@ const char *help_unknown_cmd(const char *cmd)
 		cwd[0] = '\0';
 	}
 
+	git_config(git_unknown_cmd_config, NULL);
 	if (!main_cmds.cnt && !other_cmds.cnt)
 		load_command_list("git-", &main_cmds, &other_cmds);
 
@@ -299,26 +320,39 @@ const char *help_unknown_cmd(const char *cmd)
 	if (!main_cmds.cnt)
 		die ("Uh oh.  Your system reports no Git commands at all.");
 	best_similarity = similarity(main_cmds.names[0]->name);
-	if (main_cmds.cnt < 2 ||
-	    best_similarity < similarity(main_cmds.names[1]->name)) {
+	n = 1;
+	while (n < main_cmds.cnt &&
+		best_similarity == similarity(main_cmds.names[n]->name))
+		++n;
+	if (autocorrect && n == 1) {
+		const char *assumed;
 		if (!*cwd)
 			exit(1);
 		if (chdir(cwd))
 			die ("Could not change directory back to '%s'", cwd);
+		assumed = main_cmds.names[0]->name;
+		main_cmds.names[0] = NULL;
+		clean_cmdnames(&other_cmds);
+		clean_cmdnames(&main_cmds);
 		fprintf(stderr, "WARNING: You called a Git program named '%s', "
 			"which does not exist.\n"
 			"Continuing under the assumption that you meant '%s'\n",
-			cmd, main_cmds.names[0]->name);
-		return main_cmds.names[0]->name;
+			cmd, assumed);
+		if (autocorrect > 0) {
+			fprintf(stderr, "in %0.1f seconds automatically...\n",
+				(float)autocorrect/10.0);
+			poll(NULL, 0, autocorrect * 100);
+		}
+		return assumed;
 	}
 
 	fprintf(stderr, "git: '%s' is not a git-command. See 'git --help'.\n", cmd);
 
 	if (best_similarity < 6) {
-		fprintf(stderr, "\nDid you mean one of these?\n");
+		fprintf(stderr, "\nDid you mean %s?\n",
+			n < 2 ? "this": "one of these");
 
-		for (i = 0; i < main_cmds.cnt && best_similarity ==
-				similarity(main_cmds.names[i]->name); i++)
+		for (i = 0; i < n; i++)
 			fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
 	}
 
-- 
1.6.0.106.g97c8

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

end of thread, other threads:[~2008-09-08  6:52 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-07-22 20:01 [FYI PATCH] git wrapper: DWIM mistyped commands Johannes Schindelin
2008-07-22 20:16 ` [SCNR] " Pierre Habouzit
2008-07-22 20:19   ` Johannes Schindelin
2008-07-22 20:34     ` Pierre Habouzit
2008-07-22 20:37 ` Alex Riesen
2008-07-22 21:03   ` [PATCH] Add help.autocorrect to enable/disable autocorrecting Alex Riesen
2008-07-22 21:08     ` Johannes Schindelin
2008-07-22 21:26       ` Alex Riesen
2008-07-22 21:44         ` Johannes Schindelin
2008-07-22 22:25           ` Alex Riesen
2008-07-23 16:44             ` Johannes Schindelin
2008-07-23 18:44               ` Alex Riesen
2008-07-23 19:00                 ` Johannes Schindelin
2008-07-23 19:04                   ` Johannes Schindelin
2008-07-22 23:08           ` Junio C Hamano
2008-07-23 16:41             ` [PATCH] Wait help.autocorrect deciseconds before running corrected command Alex Riesen
2008-07-23 16:57               ` Johannes Schindelin
2008-07-23 18:45                 ` Alex Riesen
2008-07-22 23:05 ` [FYI PATCH] git wrapper: DWIM mistyped commands Junio C Hamano
2008-07-22 23:10   ` Sverre Rabbelier
2008-08-28 17:15 [PATCH] Remove calculation of the longest command name from where it is not used Alex Riesen, Alex Riesen
2008-08-28 21:27 ` [PATCH updated] git wrapper: DWIM mistyped commands Alex Riesen
2008-08-28 21:28   ` [PATCH] Add help.autocorrect to enable/disable autocorrecting Alex Riesen
2008-08-29 10:11     ` Andreas Ericsson
2008-09-08  6:50     ` Junio C Hamano
2008-08-30 15:36   ` [PATCH updated] git wrapper: DWIM mistyped commands Junio C Hamano
2008-08-30 16:44     ` Alex Riesen
2008-08-30 17:13       ` [PATCH] Reuse cmdname->len to store pre-calculated similarity indexes Alex Riesen
2008-08-30 17:26         ` Junio C Hamano
2008-08-31 13:50           ` [PATCH] git wrapper: DWIM mistyped commands Alex Riesen
2008-08-31 13:54             ` [PATCH] Add help.autocorrect to enable/disable autocorrecting Alex Riesen
2008-08-31 14:49               ` Matthieu Moy
2008-08-31 16:33                 ` Junio C Hamano

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 NNTP newsgroup(s).