threads / patch / 13807

patchgit wrapper: show similar command names for an unknown command

Subject: [TOY PATCH] git wrapper: show similar command names for an unknown command

## tl;dr

28 messages between Jun 5, 2008 and Jun 8, 2008. Diffs are folded; open one to read it.

replies: 27people: 10as markdown or json

Johannes Schindelin· Jun 5, 2008, 06:48 UTC · lore

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 reabse
	git: 'reabse' is not a git-command. See 'git --help'.
	Did you mean one of these?
		rebase
		merge-base
		rev-parse
		remote
		rerere
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
---
	This is just a toy, but might be useful to other people.
 Makefile      |    2 ++
 help.c        |   43 +++++++++++++++++++++++++++++++++++++++++++
 levenshtein.c |   47 +++++++++++++++++++++++++++++++++++++++++++++++
 levenshtein.h |    8 ++++++++
 4 files changed, 100 insertions(+), 0 deletions(-)
 create mode 100644 levenshtein.c
 create mode 100644 levenshtein.h
Show changes to 4 files +100 −0

Makefile, help.c, levenshtein.c, levenshtein.h

diff --git a/Makefile b/Makefile
index cce5a6e..df48af2 100644
--- a/Makefile
+++ b/Makefile
@@ -376,6 +376,7 @@ LIB_H += tree-walk.h
 LIB_H += unpack-trees.h
 LIB_H += utf8.h
 LIB_H += wt-status.h
+LIB_H += levenshtein.h
 
 LIB_OBJS += alias.o
 LIB_OBJS += alloc.o
@@ -471,6 +472,7 @@ LIB_OBJS += write_or_die.o
 LIB_OBJS += ws.o
 LIB_OBJS += wt-status.o
 LIB_OBJS += xdiff-interface.o
+LIB_OBJS += levenshtein.o
 
 BUILTIN_OBJS += builtin-add.o
 BUILTIN_OBJS += builtin-annotate.o
diff --git a/help.c b/help.c
index d89d437..ac29225 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;
@@ -623,9 +624,51 @@ static void show_html_page(const char *git_cmd)
 	execl_git_cmd("web--browse", "-c", "help.browser", page_path.buf, NULL);
 }
 
+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);
+}
+
 void help_unknown_cmd(const char *cmd)
 {
+	int i, header_shown = 0;
+
 	fprintf(stderr, "git: '%s' is not a git-command. See 'git --help'.\n", cmd);
+
+	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);
+
+	for (i = 0; i < main_cmds.cnt; i++) {
+		int s = similarity(main_cmds.names[i]->name);
+		if (s > 6)
+			break;
+		if (!i) {
+			fprintf(stderr, "\nDid you mean %s?\n",
+				main_cmds.cnt < 2 ||
+				similarity(main_cmds.names[1]->name) > 6 ?
+				"this" : "one of these");
+			header_shown = 1;
+		}
+		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.5.6.rc1.167.gce972
Teemu Likonen· Jun 5, 2008, 08:19 UTC · re: Johannes Schindelin · lore

[PATCH] Add subcommand "help" to the list of most commonly used subcommands

Johannes Schindelin wrote (2008-06-05 07:48 +0100):
> A typical output would now look like this:
> 
> 	$ git reabse
> 	git: 'reabse' is not a git-command. See 'git --help'.
A side note: The following three commands seem to do exactly the same:
  $ git --help log
  $ git log --help
  $ git help log

Which in itself is good, I think, since in all the cases user expects to get the manual for "log". It seems that "git help <command>" is the most often advertised in manuals and tutorials but it does not show in the list printed by "git / git --help / git help":

  $ git
  usage: [...]
  The most commonly used git commands are:
  [There's no "help" command in the list.]

I think it belongs there, so how about the following patch? There are two logically separate changes but I didn't feel that they deserve separate commits.

---snip--- Add subcommand "help" to the list of most commonly used subcommands

Commands "git", "git --help" and "git help" did not list the subcommand "help" as one of the most commonly used git commands. Yet "git help" is advertised as the help command of git so this patch adds "help" the list.

In addition to that change the short description in git-help.txt manual to start with a capital letter.

Signed-off-by: Teemu Likonen <tlikonen@iki.fi>
---
 Documentation/git-help.txt |    2 +-
 command-list.txt           |    2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)
Show changes to 2 files +2 −2

Documentation/git-help.txt, command-list.txt

diff --git a/Documentation/git-help.txt b/Documentation/git-help.txt
index bfbba9e..4d3613c 100644
--- a/Documentation/git-help.txt
+++ b/Documentation/git-help.txt
@@ -3,7 +3,7 @@ git-help(1)
 
 NAME
 ----
-git-help - display help information about git
+git-help - Display help information about git
 
 SYNOPSIS
 --------
diff --git a/command-list.txt b/command-list.txt
index 3583a33..510ac69 100644
--- a/command-list.txt
+++ b/command-list.txt
@@ -47,7 +47,7 @@ git-get-tar-commit-id                   ancillaryinterrogators
 git-grep                                mainporcelain common
 git-gui                                 mainporcelain
 git-hash-object                         plumbingmanipulators
-git-help				ancillaryinterrogators
+git-help				ancillaryinterrogators common
 git-http-fetch                          synchelpers
 git-http-push                           synchelpers
 git-imap-send                           foreignscminterface
-- 
1.5.6.rc1.15.gc0c85
Johannes Schindelin· Jun 5, 2008, 10:32 UTC · re: Teemu Likonen · lore

Re: [PATCH] Add subcommand "help" to the list of most commonly used subcommands

Hi,
On Thu, 5 Jun 2008, Teemu Likonen wrote:
> Add subcommand "help" to the list of most commonly used subcommands

Hrmpf. IMO "help" is not really a _git_ command. And I use it really, really rarely.

Ciao, Dscho

Teemu Likonen· Jun 5, 2008, 10:52 UTC · re: Johannes Schindelin · lore

Re: [PATCH] Add subcommand "help" to the list of most commonly used subcommands

Johannes Schindelin wrote (2008-06-05 11:32 +0100):
Show 6 quoted lines
> On Thu, 5 Jun 2008, Teemu Likonen wrote:
> 
> > Add subcommand "help" to the list of most commonly used subcommands
> 
> Hrmpf.  IMO "help" is not really a _git_ command.  And I use it
> really, really rarely.

But you know git inside out, don't you? It seems common to have such help command: svn help, bzr help, hg help. They all list "help" as one of the subcommands. I don't know anything about "being really a git command" but from user interface's point of view "git help" is a git command. It's even advertised in output of other git commands (well, at least "git gc --auto").

Anyway, I'd change the short description of "git help" to be more informative so I'd separate the changes. Version 2 follows.

Teemu Likonen· Jun 5, 2008, 10:57 UTC · re: Teemu Likonen · lore

[PATCH v2 1/2] Add subcommand "help" to the list of most commonly used subcommands

Commands "git", "git --help" and "git help" did not list the subcommand "help" as one of the most commonly used git commands. Yet "git help" is advertised as the help command of git so this patch adds "help" the list.

Signed-off-by: Teemu Likonen <tlikonen@iki.fi>
---
 command-list.txt |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
Show changes to command-list.txt +1 −1
diff --git a/command-list.txt b/command-list.txt
index 3583a33..510ac69 100644
--- a/command-list.txt
+++ b/command-list.txt
@@ -47,7 +47,7 @@ git-get-tar-commit-id                   ancillaryinterrogators
 git-grep                                mainporcelain common
 git-gui                                 mainporcelain
 git-hash-object                         plumbingmanipulators
-git-help				ancillaryinterrogators
+git-help				ancillaryinterrogators common
 git-http-fetch                          synchelpers
 git-http-push                           synchelpers
 git-imap-send                           foreignscminterface
-- 
1.5.6.rc1.17.gfc76f
Teemu Likonen· Jun 5, 2008, 10:57 UTC · re: Teemu Likonen · lore

[PATCH v2 2/2] More informative short description for git-help.txt

Signed-off-by: Teemu Likonen <tlikonen@iki.fi>
---
 Documentation/git-help.txt |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
Show changes to Documentation/git-help.txt +1 −1
diff --git a/Documentation/git-help.txt b/Documentation/git-help.txt
index bfbba9e..4df3791 100644
--- a/Documentation/git-help.txt
+++ b/Documentation/git-help.txt
@@ -3,7 +3,7 @@ git-help(1)
 
 NAME
 ----
-git-help - display help information about git
+git-help - Display help information about git commands and other topics
 
 SYNOPSIS
 --------
-- 
1.5.6.rc1.17.gfc76f
Johannes Schindelin· Jun 5, 2008, 12:58 UTC · re: Teemu Likonen · lore

Re: [PATCH] Add subcommand "help" to the list of most commonly used subcommands

Hi,
On Thu, 5 Jun 2008, Teemu Likonen wrote:
Show 11 quoted lines
> Johannes Schindelin wrote (2008-06-05 11:32 +0100):
> 
> > On Thu, 5 Jun 2008, Teemu Likonen wrote:
> > 
> > > Add subcommand "help" to the list of most commonly used subcommands
> > 
> > Hrmpf.  IMO "help" is not really a _git_ command.  And I use it
> > really, really rarely.
> 
> But you know git inside out, don't you? It seems common to have such
> help command: svn help, bzr help, hg help.

Oh, I was not talking about how common that command is, but how commonly used.

And I would be quite annoyed by "git help" telling me that there is a "help" command as well; how does it think I got the list to begin with? Of course I used "git help", so I know that command already, and do not need it listed with more interesting commands.

Whatever, Dscho

Sverre Rabbelier· Jun 5, 2008, 11:21 UTC · re: Johannes Schindelin · lore

Re: [PATCH] Add subcommand "help" to the list of most commonly used subcommands

On Thu, Jun 5, 2008 at 12:32 PM, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:

Show 5 quoted lines
> On Thu, 5 Jun 2008, Teemu Likonen wrote:
>> Add subcommand "help" to the list of most commonly used subcommands
>
> Hrmpf.  IMO "help" is not really a _git_ command.  And I use it really,
> really rarely.

I agree with this, but not because I don't use it rarely, but because there is no such command 'git-help'. I know that we are urging the user away from the dash notation, but if we want to advertise 'git help' as an actual command, at least make 'git' recognize it as an actual command instead of displaying the default usage notice (type 'git help' and see what I mean).

-- 
Cheers,

Sverre Rabbelier
Teemu Likonen· Jun 5, 2008, 13:22 UTC · re: Sverre Rabbelier · lore

Re: [PATCH] Add subcommand "help" to the list of most commonly used subcommands

Sverre Rabbelier wrote (2008-06-05 13:21 +0200):
Show 14 quoted lines
> On Thu, Jun 5, 2008 at 12:32 PM, Johannes Schindelin
> <Johannes.Schindelin@gmx.de> wrote:
> > On Thu, 5 Jun 2008, Teemu Likonen wrote:
> >> Add subcommand "help" to the list of most commonly used subcommands
> >
> > Hrmpf.  IMO "help" is not really a _git_ command.  And I use it
> > really, really rarely.
> 
> I agree with this, but not because I don't use it rarely, but because
> there is no such command 'git-help'. I know that we are urging the
> user away from the dash notation, but if we want to advertise 'git
> help' as an actual command, at least make 'git' recognize it as an
> actual command instead of displaying the default usage notice (type
> 'git help' and see what I mean).

Well, you guys know the internals, I don't, but I have to admit that your opinions sound weird to me at the moment. I mean, what's the purpose of the command list printed after typing just "git"? To help users, I'd say. Making help commands/options easily available is for the same purpose. If manuals, mailing lists, web pages, IRC logs and your grandmothers advertise "git help" as _the_ help command but at the same time user can't find the command advertised in the git's own "metahelp" page it's quite confusing.

I came up with this suggestion because of my personal confusion. Command "git" speaks only about --help option and I was coming to a conclusion that "git help" is deprecated and instructions are just out-of-date. Then I read the "git help help" manual and saw that actually "git --help" is internally converted to "git help" so it's probably not deprecated (quite the opposite actually). And yet the front page printed by "git" does not show it.

But ok, here's another suggestion: If "git help" is not a real git command then maybe not list it with other commonly used commands. Instead print separate instructions before or after the list. Something like this:

  Type "git help <command>" for more information on a specific command
  or other topic.
Examples from other tools:
  $ hg help | grep help
   help         show help for a command, extension, or list of commands
  use "hg -v help" to show aliases and global options
  
  $ bzr help | grep help
    bzr help init      more help on e.g. init command
    bzr help commands  list all commands
    bzr help topics    list all help topics
  
  $ svn help | grep help
  Type 'svn help <subcommand>' for help on a specific subcommand.
     help (?, h)
Junio C Hamano· Jun 5, 2008, 18:13 UTC · re: Teemu Likonen · lore

Re: [PATCH] Add subcommand "help" to the list of most commonly used subcommands

Teemu Likonen <tlikonen@iki.fi> writes:
Show 7 quoted lines
>   $ git
>   usage: [...]
>
>   The most commonly used git commands are:
>   [There's no "help" command in the list.]
>
> I think it belongs there,...

While I do agree that a word 'help' should appear in the above output somewhere, it is a horrible idea to place it in "list of common commands" for two reasons.

 (1) nobody keeps typing "git help".  The reason we may want to mention
     'help' in this output is not because it is common;
 (2) 'help' _is_ different from other commands.  It is something one may
     want to know the presense of when one is still lost after seeing the
     above quoted output, especially when one is starting to learn.  It
     makes it more difficult to spot it if you bury it as one of the
     commands in a list.

It is reasonable to mention 'help' somewhere in the output, but if we are going to do this, we should make it stand out. Perhaps like this.

-- >8 -- $ git usage: git [--version] ...

The most commonly used git commands are:
   add        Add file contents to the index
   bisect     Find the change that introduced a bug by binary search
   branch     List, create, or delete branches
   ...
   show       Show various types of objects
   status     Show the working tree status
   tag        Create, list, delete or verify a tag object signed with GPG

See 'man git' and 'git help' for more information. -- 8< --

Pieter de Bie· Jun 5, 2008, 18:38 UTC · re: Junio C Hamano · lore

Re: [PATCH] Add subcommand "help" to the list of most commonly used subcommands

On 5 jun 2008, at 20:13, Junio C Hamano wrote:
> See 'man git' and 'git help' for more information.
I'd like to see something more like
See 'git help COMMAND' for more information on a specific command
- Pieter
Teemu Likonen· Jun 5, 2008, 21:15 UTC · re: Pieter de Bie · lore

Re: [PATCH] Add subcommand "help" to the list of most commonly used subcommands

Pieter de Bie wrote (2008-06-05 20:38 +0200):
Show 7 quoted lines
> On 5 jun 2008, at 20:13, Junio C Hamano wrote:
> 
> >See 'man git' and 'git help' for more information.
> 
> I'd like to see something more like
> 
> See 'git help COMMAND' for more information on a specific command

Sounds good. Here comes my first _ever_ attempt on C "programming". It implements (i.e. tries to) what pretty much seems like an agreement on the list: a separate info line after the command list. If the patch sucks, well, at least I've had fun trying. And there's no need to ask me to defend my code; I'm not able to answer. :-)

---snip--- Print info about "git help COMMAND" on git's main usage pages

Git's main usage pages did not show "git help" as a way to get more information on a specific subcommand. This patch adds an info line after the list of git commands currently printed by "git", "git help", "git --help" and "git help --all".

Signed-off-by: Teemu Likonen <tlikonen@iki.fi>
---
 builtin.h |    1 +
 git.c     |    4 ++++
 help.c    |    2 ++
 3 files changed, 7 insertions(+), 0 deletions(-)
Show changes to 3 files +7 −0

builtin.h, git.c, help.c

diff --git a/builtin.h b/builtin.h
index 8bda111..b460b2d 100644
--- a/builtin.h
+++ b/builtin.h
@@ -5,6 +5,7 @@
 
 extern const char git_version_string[];
 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);
diff --git a/git.c b/git.c
index 272bf03..15a0e71 100644
--- a/git.c
+++ b/git.c
@@ -6,6 +6,9 @@
 const char git_usage_string[] =
 	"git [--version] [--exec-path[=GIT_EXEC_PATH]] [-p|--paginate|--no-pager] [--bare] [--git-dir=GIT_DIR] [--work-tree=GIT_WORK_TREE] [--help] COMMAND [ARGS]";
 
+const char git_more_info_string[] =
+	"See 'git help COMMAND' for more information on a specific command.";
+
 static int handle_options(const char*** argv, int* argc, int* envchanged)
 {
 	int handled = 0;
@@ -427,6 +430,7 @@ int main(int argc, const char **argv)
 		/* The user didn't specify a command; give them help */
 		printf("usage: %s\n\n", git_usage_string);
 		list_common_cmds_help();
+		printf("\n%s\n", git_more_info_string);
 		exit(1);
 	}
 	cmd = argv[0];
diff --git a/help.c b/help.c
index d89d437..8aff94c 100644
--- a/help.c
+++ b/help.c
@@ -649,12 +649,14 @@ int cmd_help(int argc, const char **argv, const char *prefix)
 	if (show_all) {
 		printf("usage: %s\n\n", git_usage_string);
 		list_commands();
+		printf("%s\n", git_more_info_string);
 		return 0;
 	}
 
 	if (!argv[0]) {
 		printf("usage: %s\n\n", git_usage_string);
 		list_common_cmds_help();
+		printf("\n%s\n", git_more_info_string);
 		return 0;
 	}
 
-- 
1.5.6.rc1.16.gc6796
Junio C Hamano· Jun 5, 2008, 21:17 UTC · re: Pieter de Bie · lore

Re: [PATCH] Add subcommand "help" to the list of most commonly used subcommands

Pieter de Bie <pdebie@ai.rug.nl> writes:
Show 7 quoted lines
> On 5 jun 2008, at 20:13, Junio C Hamano wrote:
>
>> See 'man git' and 'git help' for more information.
>
> I'd like to see something more like
>
> See 'git help COMMAND' for more information on a specific command

Yeah, I think that is so far the best color of the shed I suggested "Perhaps like this".

David Symonds· Jun 6, 2008, 05:11 UTC · re: Junio C Hamano · lore

Re: [PATCH] Add subcommand "help" to the list of most commonly used subcommands

On Fri, Jun 6, 2008 at 7:17 AM, Junio C Hamano <gitster@pobox.com> wrote:
Show 12 quoted lines
> Pieter de Bie <pdebie@ai.rug.nl> writes:
>
>> On 5 jun 2008, at 20:13, Junio C Hamano wrote:
>>
>>> See 'man git' and 'git help' for more information.
>>
>> I'd like to see something more like
>>
>> See 'git help COMMAND' for more information on a specific command
>
> Yeah, I think that is so far the best color of the shed I suggested
> "Perhaps like this".
I think mauve has the most RAM.
Dave.
Wincent Colaiuta· Jun 5, 2008, 18:42 UTC · re: Junio C Hamano · lore

Re: [PATCH] Add subcommand "help" to the list of most commonly used subcommands

El 5/6/2008, a las 20:13, Junio C Hamano escribió:
Show 20 quoted lines
> It is reasonable to mention 'help' somewhere in the output, but if  
> we are
> going to do this, we should make it stand out.  Perhaps like this.
>
> -- >8 --
> $ git
> usage: git [--version] ...
>
> The most commonly used git commands are:
>   add        Add file contents to the index
>   bisect     Find the change that introduced a bug by binary search
>   branch     List, create, or delete branches
>   ...
>   show       Show various types of objects
>   status     Show the working tree status
>   tag        Create, list, delete or verify a tag object signed with  
> GPG
>
> See 'man git' and 'git help' for more information.
> -- 8< --

But if the user types "git help" they'll be presented with the exact same list of common commands again, at which point they'll probably wonder why Git suggested that.

Funnily enough, if they type "git help help" then they'll get the "git- help" man page. So, there is no command called "git-help" on the system, but from the user's perspective it walks, talks and quacks like all the "real" commands, and so they probably consider it to be one. Whether or not the "help" subcommand corresponds to a real executable or script is really just an implementation detail, I think.

Having said that, I think your suggestion is sound if it were reworded as:

   See 'man git' and 'git help [command]' for more information.

Cheers, Wincent

Sverre Rabbelier· Jun 5, 2008, 19:15 UTC · re: Wincent Colaiuta · lore

Re: [PATCH] Add subcommand "help" to the list of most commonly used subcommands

On Thu, Jun 5, 2008 at 8:42 PM, Wincent Colaiuta <win@wincent.com> wrote:
> But if the user types "git help" they'll be presented with the exact same
> list of common commands again, at which point they'll probably wonder why
> Git suggested that.
This is exactly what I meant with my earlier comment.
Show 6 quoted lines
> Funnily enough, if they type "git help help" then they'll get the "git-help"
> man page. So, there is no command called "git-help" on the system, but from
> the user's perspective it walks, talks and quacks like all the "real"
> commands, and so they probably consider it to be one. Whether or not the
> "help" subcommand corresponds to a real executable or script is really just
> an implementation detail, I think.

I fully agree here, it doesn't matter if there is a 'git-help.sh' or 'git-help' executable, as long as from the users POV there is a 'git help' command should we advertise it.

> Having said that, I think your suggestion is sound if it were reworded as:
>
>  See 'man git' and 'git help [command]' for more information.

That would be good, since it does not advertise a git help command, instead it advertises 'git help command', which clearly -is- a command (since typing 'git help command' brings up a man page).

-- 
Cheers,

Sverre Rabbelier
Dirk Süsserott· Jun 5, 2008, 20:59 UTC · re: Johannes Schindelin · lore

Re: [TOY PATCH] git wrapper: show similar command names for an unknown command

Johannes Schindelin schrieb:
Show 23 quoted lines
> 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 reabse
> 	git: 'reabse' is not a git-command. See 'git --help'.
>
> 	Did you mean one of these?
> 		rebase
> 		merge-base
> 		rev-parse
> 		remote
> 		rerere
>
> Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
> ---
> 	This is just a toy, but might be useful to other people.
>
>   
[snip]

Whow! This is really cool, especially for people that do not know the different commands by heart -- like me. I often know there's a command that's spelled somehow like X but I don't exactly remember. Your patch seems perfect for that situation. :-) Keen on seeing it in a future release. Thanks in advance. Did someone suggest it or was it your very own idea?

    -- Dirk
Johannes Schindelin· Jun 5, 2008, 23:00 UTC · re: Dirk Süsserott · lore

Re: [TOY PATCH] git wrapper: show similar command names for an unknown command

Hi,
On Thu, 5 Jun 2008, Dirk Süsserott wrote:
> This is really cool, especially for people that do not know the 
> different commands by heart -- like me. I often know there's a command 
> that's spelled somehow like X but I don't exactly remember. Your patch 
> seems perfect for that situation. :-)
Heh.
> Keen on seeing it in a future release. Thanks in advance. Did someone 
> suggest it or was it your very own idea?

Maybe someone suggested it in the past. It just happened that I wanted to procrastinate, and levenshtein.c in my personal fork came before my eyes. This was the next best thing I could think of doing with it.

In the course I realized that my extension to take swaps into account was already known as the Damerau-Levenshtein distance, so I even learnt something in the process ;-)

Ciao, Dscho

Robin Rosenberg· Jun 6, 2008, 12:15 UTC · re: Johannes Schindelin · lore

Re: [TOY PATCH] git wrapper: show similar command names for an unknown command

torsdagen den 5 juni 2008 08.48.40 skrev Johannes Schindelin:
Show 19 quoted lines
> 
> 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 reabse
> 	git: 'reabse' is not a git-command. See 'git --help'.
> 
> 	Did you mean one of these?
> 		rebase
> 		merge-base
> 		rev-parse
> 		remote
> 		rerere
> 
Sorry about my negativity here..
Doesn't this confuse more than it helps? Most people do not need to know about rerere, rev-parse or merge-base so it is very unlikely they actually meant those. That might be an issue of tuning than general principles, but I have my doubts. It won't hint that there are wildly different variants of rebase, which ctually might be much more important to know than rerere, not will it tell svn users that git revert isn't even close to svn revert.
Completion or git gui is a much better tool for solving this isssue
Some ancient LISP had a DWIM (do what I mean) and there might be a reason it has not become ery popular.
Despite not being useful, it's still cool :)
-- robin
Wincent Colaiuta· Jun 6, 2008, 14:18 UTC · re: Robin Rosenberg · lore

Re: [TOY PATCH] git wrapper: show similar command names for an unknown command

El 6/6/2008, a las 14:15, Robin Rosenberg escribió:
Show 32 quoted lines
> torsdagen den 5 juni 2008 08.48.40 skrev Johannes Schindelin:
>>
>> 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 reabse
>> 	git: 'reabse' is not a git-command. See 'git --help'.
>>
>> 	Did you mean one of these?
>> 		rebase
>> 		merge-base
>> 		rev-parse
>> 		remote
>> 		rerere
>>
> Sorry about my negativity here..
>
> Doesn't this confuse more than it helps? Most people do not need to  
> know about rerere, rev-parse or merge-base so it is very unlikely  
> they actually meant those. That might be an issue of tuning than  
> general principles, but I have my doubts. It won't hint that there  
> are wildly different variants of rebase, which ctually might be much  
> more important to know than rerere, not will it tell svn users that  
> git revert isn't even close to svn revert.
>
> Completion or git gui is a much better tool for solving this isssue

All true, but most of those issues would go away if just _one_ guess, the best guess, was shown.

Cheers, Wincent

Alex Riesen· Jun 7, 2008, 07:27 UTC · re: Johannes Schindelin · lore

Re: [TOY PATCH] git wrapper: show similar command names for an unknown command

Johannes Schindelin, Thu, Jun 05, 2008 08:48:40 +0200:
Show 12 quoted lines
> A typical output would now look like this:
> 
> 	$ git reabse
> 	git: 'reabse' is not a git-command. See 'git --help'.
> 
> 	Did you mean one of these?
> 		rebase
> 		merge-base
> 		rev-parse
> 		remote
> 		rerere
> 

That's really cool :) And I find it useful (and already applied it to my tree). For me, it works like a simple reminder about what I was about to do. Helps when working on many things at the same time (typical typo: mrge. And your patch shows it as the first hit).

BTW, you probably want to restrict the number of lines output. For instance, "git ma" (am, printed correctly in the first line) lists around 30 commands, which scrolls clear a 25 line terminal and is a lot of output anyway. I tried it with at most 5 hints:

Show changes to help.c +3 −1
diff --git a/help.c b/help.c
index ac29225..765eed8 100644
--- a/help.c
+++ b/help.c
@@ -640,7 +640,7 @@ static int levenshtein_compare(const void *p1, const void *p2)
 
 void help_unknown_cmd(const char *cmd)
 {
-	int i, header_shown = 0;
+	int i, header_shown = 0, listed = 0;
 
 	fprintf(stderr, "git: '%s' is not a git-command. See 'git --help'.\n", cmd);
 
@@ -667,6 +667,8 @@ void help_unknown_cmd(const char *cmd)
 			header_shown = 1;
 		}
 		fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
+		if (++listed >= 5)
+			break;
 	}
 
 	exit(1);
Johannes Schindelin· Jun 7, 2008, 15:04 UTC · re: Alex Riesen · lore

Re: [TOY PATCH] git wrapper: show similar command names for an unknown command

Hi,
On Sat, 7 Jun 2008, Alex Riesen wrote:
Show 22 quoted lines
> diff --git a/help.c b/help.c
> index ac29225..765eed8 100644
> --- a/help.c
> +++ b/help.c
> @@ -640,7 +640,7 @@ static int levenshtein_compare(const void *p1, const void *p2)
>  
>  void help_unknown_cmd(const char *cmd)
>  {
> -	int i, header_shown = 0;
> +	int i, header_shown = 0, listed = 0;
>  
>  	fprintf(stderr, "git: '%s' is not a git-command. See 'git --help'.\n", cmd);
>  
> @@ -667,6 +667,8 @@ void help_unknown_cmd(const char *cmd)
>  			header_shown = 1;
>  		}
>  		fprintf(stderr, "\t%s\n", main_cmds.names[i]->name);
> +		if (++listed >= 5)
> +			break;
>  	}
>  
>  	exit(1);
How about this instead?
-- snipsnap --
 help.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
Show changes to help.c +1 −1
diff --git a/help.c b/help.c
index bd51852..173e502 100644
--- a/help.c
+++ b/help.c
@@ -655,7 +655,7 @@ void help_unknown_cmd(const char *cmd)
 	qsort(main_cmds.names, main_cmds.cnt,
 	      sizeof(*main_cmds.names), levenshtein_compare);
 
-	for (i = 0; i < main_cmds.cnt; i++) {
+	for (i = 0; i < main_cmds.cnt && i < 5; i++) {
 		int s = similarity(main_cmds.names[i]->name);
 		if (s > 6)
 			break;
Alex Riesen· Jun 7, 2008, 17:51 UTC · re: Johannes Schindelin · lore

Re: [TOY PATCH] git wrapper: show similar command names for an unknown command

Johannes Schindelin, Sat, Jun 07, 2008 17:04:14 +0200:
> -	for (i = 0; i < main_cmds.cnt; i++) {
> +	for (i = 0; i < main_cmds.cnt && i < 5; i++) {

I accidentally considered "i" just the index in the global command table. Of course it is better :)

Junio C Hamano· Jun 7, 2008, 18:08 UTC · re: Alex Riesen · lore

Re: [TOY PATCH] git wrapper: show similar command names for an unknown command

Alex Riesen <raa.lkml@gmail.com> writes:
Show 6 quoted lines
> Johannes Schindelin, Sat, Jun 07, 2008 17:04:14 +0200:
>> -	for (i = 0; i < main_cmds.cnt; i++) {
>> +	for (i = 0; i < main_cmds.cnt && i < 5; i++) {
>
> I accidentally considered "i" just the index in the global command
> table. Of course it is better :)

That confusion however shows how hacky the approach to clobber the main_cmds global table by stuffing other things in it and sorting, without saying "who cares, we will exit after we are done with this processing anyway". If this patch were for inclusion, such a comment should be there immediately before it starts to muck with the command table.

Johannes Schindelin· Jun 8, 2008, 15:07 UTC · re: Junio C Hamano · lore

Re: [TOY PATCH] git wrapper: show similar command names for an unknown command

Hi,
On Sat, 7 Jun 2008, Junio C Hamano wrote:
Show 15 quoted lines
> Alex Riesen <raa.lkml@gmail.com> writes:
> 
> > Johannes Schindelin, Sat, Jun 07, 2008 17:04:14 +0200:
> >> -	for (i = 0; i < main_cmds.cnt; i++) {
> >> +	for (i = 0; i < main_cmds.cnt && i < 5; i++) {
> >
> > I accidentally considered "i" just the index in the global command
> > table. Of course it is better :)
> 
> That confusion however shows how hacky the approach to clobber the 
> main_cmds global table by stuffing other things in it and sorting, 
> without saying "who cares, we will exit after we are done with this 
> processing anyway".  If this patch were for inclusion, such a comment 
> should be there immediately before it starts to muck with the command 
> table.

This patch is not meant for inclusion, as indicated by the "TOY PATCH" prefix.

Ciao, Dscho

Junio C Hamano· Jun 8, 2008, 17:53 UTC · re: Dirk Süsserott · lore

Re: [TOY PATCH] git wrapper: show similar command names for an unknown command

Dirk Süsserott <newsletter@dirk.my1.cc> writes:
> Johannes Schindelin schrieb:
>> This patch is not meant for inclusion, as indicated by the "TOY
>> PATCH" prefix.
Yes, I understand it.

I was not complaining about the "who cares, we will exit after we are done with this processing anyway" attitude in this code. I think it is a reasonable approach to take because it is not likely that this codepath to change and would start wanting to access the original command table after it did its munging. I was suggesting a positive improvement to the patch by making it explicitly documented to help people polish further, that's all. You do not have to be so defensive.

> What a pity! :-( I liked it.
Likewise.
Johannes Schindelin· Jun 8, 2008, 23:26 UTC · re: Junio C Hamano · lore

Re: [TOY PATCH] git wrapper: show similar command names for an unknown command

Hi,
On Sun, 8 Jun 2008, Junio C Hamano wrote:
Show 15 quoted lines
> Dirk Süsserott <newsletter@dirk.my1.cc> writes:
> 
> > Johannes Schindelin schrieb:
> >> This patch is not meant for inclusion, as indicated by the "TOY
> >> PATCH" prefix.
> 
> Yes, I understand it.
> 
> I was not complaining about the "who cares, we will exit after we are 
> done with this processing anyway" attitude in this code.  I think it is 
> a reasonable approach to take because it is not likely that this 
> codepath to change and would start wanting to access the original 
> command table after it did its munging.  I was suggesting a positive 
> improvement to the patch by making it explicitly documented to help 
> people polish further, that's all.

I understood that. However, I simply do not have the time to take care of that. That's why I said it is a toy patch, and I did not mean it for inclusion. It was just a nice time waster for me; it's not even something I'd find terribly useful myself, unless it asked me if I wanted to execute this or that instead (provided that isatty()).

> You do not have to be so defensive.
I wasn't.  At least I did not mean to.

Ciao, Dscho

← back to recent threads