55#include "run-command.h"
66#include "levenshtein.h"
77#include "help.h"
8- #include "common-cmds .h"
8+ #include "command-list .h"
99#include "string-list.h"
1010#include "column.h"
1111#include "version.h"
1212#include "refs.h"
1313#include "parse-options.h"
1414
15+ struct category_description {
16+ uint32_t category ;
17+ const char * desc ;
18+ };
19+ static uint32_t common_mask =
20+ CAT_init | CAT_worktree | CAT_info |
21+ CAT_history | CAT_remote ;
22+ static struct category_description common_categories [] = {
23+ { CAT_init , N_ ("start a working area (see also: git help tutorial)" ) },
24+ { CAT_worktree , N_ ("work on the current change (see also: git help everyday)" ) },
25+ { CAT_info , N_ ("examine the history and state (see also: git help revisions)" ) },
26+ { CAT_history , N_ ("grow, mark and tweak your common history" ) },
27+ { CAT_remote , N_ ("collaborate (see also: git help workflows)" ) },
28+ { 0 , NULL }
29+ };
30+
31+ static const char * drop_prefix (const char * name )
32+ {
33+ const char * new_name ;
34+
35+ if (skip_prefix (name , "git-" , & new_name ))
36+ return new_name ;
37+ return name ;
38+
39+ }
40+
41+ static void extract_cmds (struct cmdname_help * * p_cmds , uint32_t mask )
42+ {
43+ int i , nr = 0 ;
44+ struct cmdname_help * cmds ;
45+
46+ if (ARRAY_SIZE (command_list ) == 0 )
47+ BUG ("empty command_list[] is a sign of broken generate-cmdlist.sh" );
48+
49+ ALLOC_ARRAY (cmds , ARRAY_SIZE (command_list ) + 1 );
50+
51+ for (i = 0 ; i < ARRAY_SIZE (command_list ); i ++ ) {
52+ const struct cmdname_help * cmd = command_list + i ;
53+
54+ if (!(cmd -> category & mask ))
55+ continue ;
56+
57+ cmds [nr ] = * cmd ;
58+ cmds [nr ].name = drop_prefix (cmd -> name );
59+
60+ nr ++ ;
61+ }
62+ cmds [nr ].name = NULL ;
63+ * p_cmds = cmds ;
64+ }
65+
66+ static void print_command_list (const struct cmdname_help * cmds ,
67+ uint32_t mask , int longest )
68+ {
69+ int i ;
70+
71+ for (i = 0 ; cmds [i ].name ; i ++ ) {
72+ if (cmds [i ].category & mask ) {
73+ printf (" %s " , cmds [i ].name );
74+ mput_char (' ' , longest - strlen (cmds [i ].name ));
75+ puts (_ (cmds [i ].help ));
76+ }
77+ }
78+ }
79+
80+ static int cmd_name_cmp (const void * elem1 , const void * elem2 )
81+ {
82+ const struct cmdname_help * e1 = elem1 ;
83+ const struct cmdname_help * e2 = elem2 ;
84+
85+ return strcmp (e1 -> name , e2 -> name );
86+ }
87+
88+ static void print_cmd_by_category (const struct category_description * catdesc )
89+ {
90+ struct cmdname_help * cmds ;
91+ int longest = 0 ;
92+ int i , nr = 0 ;
93+ uint32_t mask = 0 ;
94+
95+ for (i = 0 ; catdesc [i ].desc ; i ++ )
96+ mask |= catdesc [i ].category ;
97+
98+ extract_cmds (& cmds , mask );
99+
100+ for (i = 0 ; cmds [i ].name ; i ++ , nr ++ ) {
101+ if (longest < strlen (cmds [i ].name ))
102+ longest = strlen (cmds [i ].name );
103+ }
104+ QSORT (cmds , nr , cmd_name_cmp );
105+
106+ for (i = 0 ; catdesc [i ].desc ; i ++ ) {
107+ uint32_t mask = catdesc [i ].category ;
108+ const char * desc = catdesc [i ].desc ;
109+
110+ printf ("\n%s\n" , _ (desc ));
111+ print_command_list (cmds , mask , longest );
112+ }
113+ free (cmds );
114+ }
115+
15116void add_cmdname (struct cmdnames * cmds , const char * name , int len )
16117{
17118 struct cmdname * ent ;
@@ -190,42 +291,10 @@ void list_commands(unsigned int colopts,
190291 }
191292}
192293
193- static int cmd_group_cmp (const void * elem1 , const void * elem2 )
194- {
195- const struct cmdname_help * e1 = elem1 ;
196- const struct cmdname_help * e2 = elem2 ;
197-
198- if (e1 -> group < e2 -> group )
199- return -1 ;
200- if (e1 -> group > e2 -> group )
201- return 1 ;
202- return strcmp (e1 -> name , e2 -> name );
203- }
204-
205294void list_common_cmds_help (void )
206295{
207- int i , longest = 0 ;
208- int current_grp = -1 ;
209-
210- for (i = 0 ; i < ARRAY_SIZE (common_cmds ); i ++ ) {
211- if (longest < strlen (common_cmds [i ].name ))
212- longest = strlen (common_cmds [i ].name );
213- }
214-
215- QSORT (common_cmds , ARRAY_SIZE (common_cmds ), cmd_group_cmp );
216-
217296 puts (_ ("These are common Git commands used in various situations:" ));
218-
219- for (i = 0 ; i < ARRAY_SIZE (common_cmds ); i ++ ) {
220- if (common_cmds [i ].group != current_grp ) {
221- printf ("\n%s\n" , _ (common_cmd_groups [common_cmds [i ].group ]));
222- current_grp = common_cmds [i ].group ;
223- }
224-
225- printf (" %s " , common_cmds [i ].name );
226- mput_char (' ' , longest - strlen (common_cmds [i ].name ));
227- puts (_ (common_cmds [i ].help ));
228- }
297+ print_cmd_by_category (common_categories );
229298}
230299
231300int is_in_cmdlist (struct cmdnames * c , const char * s )
@@ -285,6 +354,7 @@ const char *help_unknown_cmd(const char *cmd)
285354{
286355 int i , n , best_similarity = 0 ;
287356 struct cmdnames main_cmds , other_cmds ;
357+ struct cmdname_help * common_cmds ;
288358
289359 memset (& main_cmds , 0 , sizeof (main_cmds ));
290360 memset (& other_cmds , 0 , sizeof (other_cmds ));
@@ -299,6 +369,8 @@ const char *help_unknown_cmd(const char *cmd)
299369 QSORT (main_cmds .names , main_cmds .cnt , cmdname_compare );
300370 uniq (& main_cmds );
301371
372+ extract_cmds (& common_cmds , common_mask );
373+
302374 /* This abuses cmdname->len for levenshtein distance */
303375 for (i = 0 , n = 0 ; i < main_cmds .cnt ; i ++ ) {
304376 int cmp = 0 ; /* avoid compiler stupidity */
@@ -313,10 +385,10 @@ const char *help_unknown_cmd(const char *cmd)
313385 die (_ (bad_interpreter_advice ), cmd , cmd );
314386
315387 /* Does the candidate appear in common_cmds list? */
316- while (n < ARRAY_SIZE ( common_cmds ) &&
388+ while (common_cmds [ n ]. name &&
317389 (cmp = strcmp (common_cmds [n ].name , candidate )) < 0 )
318390 n ++ ;
319- if (( n < ARRAY_SIZE ( common_cmds )) && !cmp ) {
391+ if (common_cmds [ n ]. name && !cmp ) {
320392 /* Yes, this is one of the common commands */
321393 n ++ ; /* use the entry from common_cmds[] */
322394 if (starts_with (candidate , cmd )) {
@@ -329,6 +401,7 @@ const char *help_unknown_cmd(const char *cmd)
329401 main_cmds .names [i ]-> len =
330402 levenshtein (cmd , candidate , 0 , 2 , 1 , 3 ) + 1 ;
331403 }
404+ FREE_AND_NULL (common_cmds );
332405
333406 QSORT (main_cmds .names , main_cmds .cnt , levenshtein_compare );
334407
0 commit comments