Skip to content

Commit cfb22a0

Browse files
pcloudsgitster
authored andcommitted
help: use command-list.h for common command list
The previous commit added code generation for all_cmd_desc[] which includes almost everything we need to generate common command list. Convert help code to use that array instead and drop common_cmds[] array. The description of each common command group is removed from command-list.txt. This keeps this file format simpler. common-cmds.h will not be generated correctly after this change due to the command-list.txt format change. But it does not matter and common-cmds.h will be removed. Signed-off-by: Nguyễn Thái Ngọc Duy <[email protected]> Signed-off-by: Junio C Hamano <[email protected]>
1 parent f318d73 commit cfb22a0

File tree

5 files changed

+122
-50
lines changed

5 files changed

+122
-50
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1914,9 +1914,9 @@ git$X: git.o GIT-LDFLAGS $(BUILTIN_OBJS) $(GITLIBS)
19141914
$(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \
19151915
$(filter %.o,$^) $(LIBS)
19161916

1917-
help.sp help.s help.o: common-cmds.h
1917+
help.sp help.s help.o: common-cmds.h command-list.h
19181918

1919-
builtin/help.sp builtin/help.s builtin/help.o: common-cmds.h GIT-PREFIX
1919+
builtin/help.sp builtin/help.s builtin/help.o: common-cmds.h command-list.h GIT-PREFIX
19201920
builtin/help.sp builtin/help.s builtin/help.o: EXTRA_CPPFLAGS = \
19211921
'-DGIT_HTML_PATH="$(htmldir_relative_SQ)"' \
19221922
'-DGIT_MAN_PATH="$(mandir_relative_SQ)"' \

command-list.txt

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,3 @@
1-
# common commands are grouped by themes
2-
# these groups are output by 'git help' in the order declared here.
3-
# map each common command in the command list to one of these groups.
4-
### common groups (do not change this line)
5-
init start a working area (see also: git help tutorial)
6-
worktree work on the current change (see also: git help everyday)
7-
info examine the history and state (see also: git help revisions)
8-
history grow, mark and tweak your common history
9-
remote collaborate (see also: git help workflows)
10-
111
### command list (do not change this line, also do not change alignment)
122
# command name category [category] [category]
133
git-add mainporcelain worktree

generate-cmdlist.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ die () {
66
}
77

88
command_list () {
9-
sed '1,/^### command list/d;/^#/d' "$1"
9+
grep -v '^#' "$1"
1010
}
1111

1212
get_categories () {
@@ -65,7 +65,7 @@ echo "/* Automatically generated by generate-cmdlist.sh */
6565
struct cmdname_help {
6666
const char *name;
6767
const char *help;
68-
uint32_t group;
68+
uint32_t category;
6969
};
7070
"
7171
if test -z "$2"

help.c

Lines changed: 109 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,114 @@
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+
15116
void 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-
205294
void 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

231300
int 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

t/t0012-help.sh

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ test_expect_success "--help does not work for guides" "
4949
test_i18ncmp expect actual
5050
"
5151

52+
test_expect_success 'git help' '
53+
git help >help.output &&
54+
test_i18ngrep "^ clone " help.output &&
55+
test_i18ngrep "^ add " help.output &&
56+
test_i18ngrep "^ log " help.output &&
57+
test_i18ngrep "^ commit " help.output &&
58+
test_i18ngrep "^ fetch " help.output
59+
'
60+
5261
test_expect_success 'generate builtin list' '
5362
git --list-builtins >builtins
5463
'

0 commit comments

Comments
 (0)