db9465b9ca58be08a08731741b985c75fe5ca0f2
[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 VscCliCommandInfo *command_info,
40        const struct VscCliOption *option_list, 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,
57        const struct VscCliCommandInfo *command_info VSC__ATTR__UNUSED,
58        const struct VscCliOption *option_list,
59        void *user_data VSC__ATTR__UNUSED)
60 {
61         int i;
62         const char *command_name;
63         const struct VscCliCommandInfo *command_info_;
64         const struct VscCliOptionInfo *option_info;
65
66         VSC__ASSERT (error != NULL);
67         VSC__ASSERT (! error->occured);
68
69         command_name = vsc_cli_option_get_string (option_list, "command");
70
71         if (command_name != NULL) {
72                 command_info_ = _vsc_cli_command_info_lookup (command_name);
73
74                 if (command_info_ == NULL) {
75                         VSC__ERROR2 (error, VSC__ERROR_CODE__INTERNAL_ERROR,
76                                      "help: Command '%s' is unknown", command_name);
77                         return;
78                 }
79
80                 printf (_vsc_cli_output_coloring ? "\033[1mNAME\033[0m\n"
81                                                  : "NAME\n");
82                 printf ("       %s - %s\n", command_info_->name, command_info_->help);
83                 printf ("\n");
84
85                 printf (_vsc_cli_output_coloring ? "\033[1mSYNOPSIS\033[0m\n"
86                                                  : "SYNOPSIS\n");
87                 printf ("       %s", command_info_->name);
88
89                 for (i = 0; command_info_->option_infos[i].long_name != NULL; ++i) {
90                         option_info = &command_info_->option_infos[i];
91
92                         if (option_info->required) {
93                                 printf (" %s", _vsc_cli_option_syntax (option_info, TRUE));
94                         } else {
95                                 printf (" [%s]", _vsc_cli_option_syntax (option_info, TRUE));
96                         }
97                 }
98
99                 printf ("\n");
100
101                 if (command_info_->description != NULL &&
102                     *command_info_->description != '\0') {
103                         printf ("\n");
104                         printf (_vsc_cli_output_coloring ? "\033[1mDESCRIPTION\033[0m\n"
105                                                          : "DESCRIPTION\n");
106                         printf ("       %s\n", command_info_->description);
107                 }
108
109                 if (command_info_->option_infos[0].long_name != NULL) {
110                         printf ("\n");
111                         printf (_vsc_cli_output_coloring ? "\033[1mOPTIONS\033[0m\n"
112                                                          : "OPTIONS\n");
113
114                         for (i = 0; command_info_->option_infos[i].long_name != NULL; ++i) {
115                                 option_info = &command_info_->option_infos[i];
116
117                                 printf ("       %s\n"
118                                         "              %s\n",
119                                         _vsc_cli_option_syntax (option_info, FALSE),
120                                         option_info->help);
121
122                                 if (command_info_->option_infos[i + 1].long_name != NULL) {
123                                         printf ("\n");
124                                 }
125                         }
126                 }
127         } else {
128                 if (! _vsc_cli_interactive) {
129                         printf (_vsc_cli_output_coloring ? "\033[1mNAME\033[0m\n" : "NAME\n");
130                         printf ("       %s - %s\n", _vsc_cli_name, _vsc_cli_help);
131                         printf ("\n");
132
133                         printf (_vsc_cli_output_coloring ? "\033[1mSYNOPSIS\033[0m\n"
134                                                          : "SYNOPSIS\n");
135                         printf ("       %s", _vsc_cli_name);
136
137                         for (i = 0; _vsc_cli_option_infos[i].long_name != NULL; ++i) {
138                                 option_info = &_vsc_cli_option_infos[i];
139
140                                 if (option_info->required) {
141                                         printf (" %s", _vsc_cli_option_syntax (option_info, TRUE));
142                                 } else {
143                                         printf (" [%s]", _vsc_cli_option_syntax (option_info, TRUE));
144                                 }
145                         }
146
147                         printf (" [<command>[, <command>]...]\n");
148
149                         if (_vsc_cli_option_infos[0].long_name != NULL) {
150                                 printf ("\n");
151                                 printf (_vsc_cli_output_coloring ? "\033[1mOPTIONS\033[0m\n"
152                                                                  : "OPTIONS\n");
153
154                                 for (i = 0; _vsc_cli_option_infos[i].long_name != NULL; ++i) {
155                                         option_info = &_vsc_cli_option_infos[i];
156
157                                         printf ("       %s\n"
158                                                 "              %s\n",
159                                                 _vsc_cli_option_syntax (option_info, FALSE),
160                                                 option_info->help);
161
162                                         if (_vsc_cli_option_infos[i + 1].long_name != NULL) {
163                                                 printf ("\n");
164                                         }
165                                 }
166                         }
167                 }
168
169                 if (_vsc_cli_command_infos[0]->name != NULL) {
170                         if (! _vsc_cli_interactive) {
171                                 printf ("\n");
172                         }
173
174                         printf (_vsc_cli_output_coloring ? "\033[1mCOMMANDS\033[0m\n"
175                                                          : "COMMANDS\n");
176
177                         for (i = 0; _vsc_cli_command_infos[i] != NULL; ++i) {
178                                 printf ("       %-20s  %s\n", _vsc_cli_command_infos[i]->name,
179                                         _vsc_cli_command_infos[i]->help);
180                         }
181                 }
182         }
183 }