common-cmds.h is used to extract the list of common commands (by
group) and a one-line summary of each command. Some information is
dropped, for example command category or summary of other commands.
Update generate-cmdlist.sh to keep all the information. The extra info
will be used shortly.

Signed-off-by: Nguyễn Thái Ngọc Duy <pclo...@gmail.com>
---
 generate-cmdlist.sh | 46 ++++++++++++++++++++++++++++++++++-----------
 help.c              | 43 ++++++++++++++++++++++++++++++++++++------
 2 files changed, 72 insertions(+), 17 deletions(-)

diff --git a/generate-cmdlist.sh b/generate-cmdlist.sh
index eeea4b67ea..72235e7296 100755
--- a/generate-cmdlist.sh
+++ b/generate-cmdlist.sh
@@ -2,9 +2,10 @@
 
 echo "/* Automatically generated by generate-cmdlist.sh */
 struct cmdname_help {
-       char name[16];
+       char name[32];
        char help[80];
-       unsigned char group;
+       unsigned int category;
+       unsigned int group;
 };
 
 static const char *common_cmd_groups[] = {"
@@ -23,27 +24,50 @@ sed -n '
        ' "$1"
 printf '};\n\n'
 
+echo "#define GROUP_NONE 0xff /* no common group */"
+echo "#define GROUP_ 0xff /* no common group */"
 n=0
-substnum=
 while read grp
 do
-       echo "^git-..*[         ]$grp"
-       substnum="$substnum${substnum:+;}s/[    ]$grp/$n/"
+       echo "#define GROUP_$grp $n"
        n=$(($n+1))
-done <"$grps" >"$match"
+done <"$grps"
+echo
 
-printf 'static struct cmdname_help common_cmds[] = {\n'
-grep -f "$match" "$1" |
+echo '/*'
+printf 'static const char *cmd_categories[] = {\n'
+grep '^git-' "$1" |
+awk '{print $2;}' |
+sort |
+uniq |
+while read category; do
+       printf '\t\"'$category'\",\n'
+done
+printf '\tNULL\n};\n\n'
+echo '*/'
+
+n=0
+grep '^git-' "$1" |
+awk '{print $2;}' |
+sort |
+uniq |
+while read category; do
+       echo "#define CAT_$category $n"
+       n=$(($n+1))
+done
+echo
+
+printf 'static struct cmdname_help command_list[] = {\n'
+grep "^git-" "$1" |
 sed 's/^git-//' |
 sort |
-while read cmd tags
+while read cmd category tags
 do
-       tag=$(echo "$tags" | sed "$substnum; s/[^0-9]//g")
        sed -n '
                /^NAME/,/git-'"$cmd"'/H
                ${
                        x
-                       s/.*git-'"$cmd"' - \(.*\)/      {"'"$cmd"'", N_("\1"), 
'$tag'},/
+                       s/.*git-'"$cmd"' - \(.*\)/      {"'"$cmd"'", N_("\1"), 
CAT_'$category', GROUP_'$tags' },/
                        p
                }' "Documentation/git-$cmd.txt"
 done
diff --git a/help.c b/help.c
index f3f35dfbb1..4d07ea3913 100644
--- a/help.c
+++ b/help.c
@@ -190,6 +190,28 @@ void list_commands(unsigned int colopts,
        }
 }
 
+static void extract_common_cmds(struct cmdname_help **p_common_cmds,
+                               int *p_nr)
+{
+       int i, nr = 0;
+       struct cmdname_help *common_cmds;
+
+       ALLOC_ARRAY(common_cmds, ARRAY_SIZE(command_list));
+
+       for (i = 0; i < ARRAY_SIZE(command_list); i++) {
+               const struct cmdname_help *cmd = command_list + i;
+
+               if (cmd->category != CAT_mainporcelain ||
+                   cmd->group == GROUP_NONE)
+                       continue;
+
+               common_cmds[nr++] = *cmd;
+       }
+
+       *p_common_cmds = common_cmds;
+       *p_nr = nr;
+}
+
 static int cmd_group_cmp(const void *elem1, const void *elem2)
 {
        const struct cmdname_help *e1 = elem1;
@@ -206,17 +228,21 @@ void list_common_cmds_help(void)
 {
        int i, longest = 0;
        int current_grp = -1;
+       int nr = 0;
+       struct cmdname_help *common_cmds;
+
+       extract_common_cmds(&common_cmds, &nr);
 
-       for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
+       for (i = 0; i < nr; i++) {
                if (longest < strlen(common_cmds[i].name))
                        longest = strlen(common_cmds[i].name);
        }
 
-       QSORT(common_cmds, ARRAY_SIZE(common_cmds), cmd_group_cmp);
+       QSORT(common_cmds, nr, cmd_group_cmp);
 
        puts(_("These are common Git commands used in various situations:"));
 
-       for (i = 0; i < ARRAY_SIZE(common_cmds); i++) {
+       for (i = 0; i < nr; i++) {
                if (common_cmds[i].group != current_grp) {
                        printf("\n%s\n", 
_(common_cmd_groups[common_cmds[i].group]));
                        current_grp = common_cmds[i].group;
@@ -226,6 +252,7 @@ void list_common_cmds_help(void)
                mput_char(' ', longest - strlen(common_cmds[i].name));
                puts(_(common_cmds[i].help));
        }
+       free(common_cmds);
 }
 
 void list_all_cmds(void)
@@ -298,8 +325,9 @@ static const char bad_interpreter_advice[] =
 
 const char *help_unknown_cmd(const char *cmd)
 {
-       int i, n, best_similarity = 0;
+       int i, n, best_similarity = 0, nr_common;
        struct cmdnames main_cmds, other_cmds;
+       struct cmdname_help *common_cmds;
 
        memset(&main_cmds, 0, sizeof(main_cmds));
        memset(&other_cmds, 0, sizeof(other_cmds));
@@ -314,6 +342,8 @@ const char *help_unknown_cmd(const char *cmd)
        QSORT(main_cmds.names, main_cmds.cnt, cmdname_compare);
        uniq(&main_cmds);
 
+       extract_common_cmds(&common_cmds, &nr_common);
+
        /* This abuses cmdname->len for levenshtein distance */
        for (i = 0, n = 0; i < main_cmds.cnt; i++) {
                int cmp = 0; /* avoid compiler stupidity */
@@ -328,10 +358,10 @@ const char *help_unknown_cmd(const char *cmd)
                        die(_(bad_interpreter_advice), cmd, cmd);
 
                /* Does the candidate appear in common_cmds list? */
-               while (n < ARRAY_SIZE(common_cmds) &&
+               while (n < nr_common &&
                       (cmp = strcmp(common_cmds[n].name, candidate)) < 0)
                        n++;
-               if ((n < ARRAY_SIZE(common_cmds)) && !cmp) {
+               if ((n < nr_common) && !cmp) {
                        /* Yes, this is one of the common commands */
                        n++; /* use the entry from common_cmds[] */
                        if (starts_with(candidate, cmd)) {
@@ -344,6 +374,7 @@ const char *help_unknown_cmd(const char *cmd)
                main_cmds.names[i]->len =
                        levenshtein(cmd, candidate, 0, 2, 1, 3) + 1;
        }
+       FREE_AND_NULL(common_cmds);
 
        QSORT(main_cmds.names, main_cmds.cnt, levenshtein_compare);
 
-- 
2.17.0.rc0.348.gd5a49e0b6f

Reply via email to