a45ab2ebe0cc8c7598f114e0a3a3bc1722ced1d1
[vsc-common.git] / cli / help.c
1 /*
2  * help.c: Library for interactive commandline interfaces
3  *
4  * Copyright (C) 2009 Matthias Bolte <matthias.bolte@googlemail.com>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
19  */
20
21 #include <stdio.h>
22
23 #include <libvscmisc/assert.h>
24 #include <libvscmisc/error.h>
25
26 #include "../include/libvsccli/help.h"
27 #include "../include/libvsccli/option.h"
28 #include "command.h"
29 #include "option.h"
30
31 extern const char *_vsc_cli_name;
32 extern const char *_vsc_cli_help;
33 extern const struct VscCliOptionInfo *_vsc_cli_option_infos;
34 extern const struct VscCliCommandInfo **_vsc_cli_command_infos;
35 extern int _vsc_cli_output_coloring;
36 extern int _vsc_cli_interactive;
37
38 static void
39 _help (struct VscError *error, const struct VscCliOption *option_list,
40        void *user_data);
41
42 static const struct VscCliOptionInfo _help_option_infos[] = {
43         { -1, "command", "name of command", VSC_CLI__OPTION_TYPE__DATA, FALSE },
44         { -1, NULL, NULL, 0, FALSE },
45 };
46
47 const struct VscCliCommandInfo vsc_cli_help_command_info = {
48         "help",
49         "print help",
50         "Prints global or command specific help",
51         _help,
52         _help_option_infos,
53 };
54
55 static void
56 _help (struct VscError *error, const struct VscCliOption *option_list,
57        void *user_data VSC__ATTR__UNUSED)
58 {
59         int i;
60         const char *command_name;
61         const struct VscCliCommandInfo *command_info;
62         const struct VscCliOptionInfo *option_info;
63
64         VSC__ASSERT (error != NULL);
65         VSC__ASSERT (! error->occured);
66
67         command_name = vsc_cli_option_get_string (option_list, "command");
68
69         if (command_name != NULL) {
70                 command_info = _vsc_cli_command_info_lookup (command_name);
71
72                 if (command_info == NULL) {
73                         VSC__ERROR2 (error, VSC__ERROR_CODE__INTERNAL_ERROR,
74                                      "help: Command '%s' is unknown", command_name);
75                         return;
76                 }
77
78                 printf (_vsc_cli_output_coloring ? "\033[1mNAME\033[0m\n" : "NAME\n");
79                 printf ("       %s - %s\n", command_info->name, command_info->help);
80                 printf ("\n");
81
82                 printf (_vsc_cli_output_coloring ? "\033[1mSYNOPSIS\033[0m\n" : "SYNOPSIS\n");
83                 printf ("       %s", command_info->name);
84
85                 for (i = 0; command_info->option_infos[i].long_name != NULL; ++i) {
86                         option_info = &command_info->option_infos[i];
87
88                         if (option_info->required) {
89                                 printf (" %s", _vsc_cli_option_syntax (option_info, TRUE));
90                         } else {
91                                 printf (" [%s]", _vsc_cli_option_syntax (option_info, TRUE));
92                         }
93                 }
94
95                 printf ("\n");
96
97                 if (command_info->description != NULL &&
98                     *command_info->description != '\0') {
99                         printf ("\n");
100                         printf (_vsc_cli_output_coloring ? "\033[1mDESCRIPTION\033[0m\n"
101                                                          : "DESCRIPTION\n");
102                         printf ("       %s\n", command_info->description);
103                 }
104
105                 if (command_info->option_infos[0].long_name != NULL) {
106                         printf ("\n");
107                         printf (_vsc_cli_output_coloring ? "\033[1mOPTIONS\033[0m\n"
108                                                          : "OPTIONS\n");
109
110                         for (i = 0; command_info->option_infos[i].long_name != NULL; ++i) {
111                                 option_info = &command_info->option_infos[i];
112
113                                 printf ("       %s\n"
114                                         "              %s\n",
115                                         _vsc_cli_option_syntax (option_info, FALSE),
116                                         option_info->help);
117
118                                 if (command_info->option_infos[i + 1].long_name != NULL) {
119                                         printf ("\n");
120                                 }
121                         }
122                 }
123         } else {
124                 if (! _vsc_cli_interactive) {
125                         printf (_vsc_cli_output_coloring ? "\033[1mNAME\033[0m\n" : "NAME\n");
126                         printf ("       %s - %s\n", _vsc_cli_name, _vsc_cli_help);
127                         printf ("\n");
128
129                         printf (_vsc_cli_output_coloring ? "\033[1mSYNOPSIS\033[0m\n"
130                                                          : "SYNOPSIS\n");
131                         printf ("       %s", _vsc_cli_name);
132
133                         for (i = 0; _vsc_cli_option_infos[i].long_name != NULL; ++i) {
134                                 option_info = &_vsc_cli_option_infos[i];
135
136                                 if (option_info->required) {
137                                         printf (" %s", _vsc_cli_option_syntax (option_info, TRUE));
138                                 } else {
139                                         printf (" [%s]", _vsc_cli_option_syntax (option_info, TRUE));
140                                 }
141                         }
142
143                         printf (" [<command>[, <command>]...]\n");
144
145                         if (_vsc_cli_option_infos[0].long_name != NULL) {
146                                 printf ("\n");
147                                 printf (_vsc_cli_output_coloring ? "\033[1mOPTIONS\033[0m\n"
148                                                                  : "OPTIONS\n");
149
150                                 for (i = 0; _vsc_cli_option_infos[i].long_name != NULL; ++i) {
151                                         option_info = &_vsc_cli_option_infos[i];
152
153                                         printf ("       %s\n"
154                                                 "              %s\n",
155                                                 _vsc_cli_option_syntax (option_info, FALSE),
156                                                 option_info->help);
157
158                                         if (_vsc_cli_option_infos[i + 1].long_name != NULL) {
159                                                 printf ("\n");
160                                         }
161                                 }
162                         }
163                 }
164
165                 if (_vsc_cli_command_infos[0]->name != NULL) {
166                         if (! _vsc_cli_interactive) {
167                                 printf ("\n");
168                         }
169
170                         printf (_vsc_cli_output_coloring ? "\033[1mCOMMANDS\033[0m\n"
171                                                          : "COMMANDS\n");
172
173                         for (i = 0; _vsc_cli_command_infos[i] != NULL; ++i) {
174                                 printf ("       %-20s  %s\n", _vsc_cli_command_infos[i]->name,
175                                         _vsc_cli_command_infos[i]->help);
176                         }
177                 }
178         }
179 }