docs: Enable since/version handling for XML, CLI and ARI documentation

* Added the "since" element to the XML configObject and configOption elements
  in appdocsxml.dtd.

* Added the "Since" section to the following CLI output:
  ```
  config show help <module> <object>
  config show help <module> <object> <option>
  core show application <app>
  core show function <func>
  manager show command <command>
  manager show event <event>
  agi show commands topic <topic>
  ```

* Refactored the commands above to output their sections in the same order:
  Synopsis, Since, Description, Syntax, Arguments, SeeAlso

* Refactored the commands above so they all use the same pattern for writing
  the output to the CLI.

* Fixed several memory leaks caused by failure to free temporary output
  buffers.

* Added a "since" array to the mustache template for the top-level resources
  (Channel, Endpoint, etc.) and to the paths/methods underneath them. These
  will be added to the generated markdown if present.
  Example:
  ```
    "resourcePath": "/api-docs/channels.{format}",
    "requiresModules": [
        "res_stasis_answer",
        "res_stasis_playback",
        "res_stasis_recording",
        "res_stasis_snoop"
    ],
    "since": [
        "18.0.0",
        "21.0.0"
    ],
    "apis": [
        {
            "path": "/channels",
            "description": "Active channels",
            "operations": [
                {
                    "httpMethod": "GET",
                    "since": [
                        "18.6.0",
                        "21.8.0"
                    ],
                    "summary": "List all active channels in Asterisk.",
                    "nickname": "list",
                    "responseClass": "List[Channel]"
                },

  ```

NOTE:  No versioning information is actually added in this commit.
Those will be added separately and instructions for adding and maintaining
them will be published on the documentation site at a later date.

(cherry picked from commit 3c867e6e6c)
releases/22
George Joseph 4 months ago committed by Asterisk Development Team
parent e35d341cd7
commit 2b428734fd

@ -72,10 +72,10 @@
<!ELEMENT configFile (configObject|xi:include)+>
<!ATTLIST configFile name CDATA #REQUIRED>
<!ELEMENT configObject (synopsis?|description?|syntax?|see-also?|(configOption|xi:include))*>
<!ELEMENT configObject (since?|synopsis?|description?|syntax?|see-also?|(configOption|xi:include))*>
<!ATTLIST configObject name CDATA #REQUIRED>
<!ELEMENT configOption (synopsis,description?,syntax?,see-also?)*>
<!ELEMENT configOption (since?,synopsis,description?,syntax?,see-also?)*>
<!ATTLIST configOption name CDATA #REQUIRED>
<!ATTLIST configOption regex (yes|no|true|false) "false">
<!ATTLIST configOption default CDATA #IMPLIED>

@ -60,6 +60,10 @@ typedef struct agi_command {
struct ast_module *mod;
/*! Linked list pointer */
AST_LIST_ENTRY(agi_command) list;
/*! Since content */
const char * const since;
/*! Syntax arguments content */
const char * const arguments;
} agi_command;
/*!

@ -181,6 +181,7 @@ struct manager_action {
* function and unregistering the AMI action object.
*/
unsigned int registered:1;
AST_STRING_FIELD_EXTENDED(since); /*!< Documentation "since" element */
};
/*! \brief External routines may register/unregister manager callbacks this way

@ -150,6 +150,7 @@ struct ast_custom_function {
* \since 12 */
AST_RWLIST_ENTRY(ast_custom_function) acflist;
AST_STRING_FIELD_EXTENDED(since); /*!< Since text for 'show functions' */
};
/*! \brief All switch functions have the same interface, so define a type for them */

@ -78,6 +78,8 @@ struct ast_xml_doc_item {
struct ast_xml_node *node;
/*! The next XML documentation item that matches the same name/item type */
AST_LIST_ENTRY(ast_xml_doc_item) next;
/*! Since tagged information, if it exists */
struct ast_str *since;
};
/*! \brief Execute an XPath query on the loaded XML documentation
@ -110,6 +112,16 @@ char *ast_xmldoc_build_syntax(const char *type, const char *name, const char *mo
*/
char *ast_xmldoc_build_seealso(const char *type, const char *name, const char *module);
/*!
* \brief Parse the <since> node content.
* \param type 'application', 'function' or 'agi'.
* \param name Application or functions name.
* \param module The module the item is in (optional, can be NULL)
* \retval NULL on error.
* \retval Content of the since node.
*/
char *ast_xmldoc_build_since(const char *type, const char *name, const char *module);
/*!
* \brief Generate the [arguments] tag based on type of node ('application',
* 'function' or 'agi') and name.

@ -1244,10 +1244,14 @@ static void cli_show_module_types(struct ast_cli_args *a)
}
if (ast_str_strlen(item->synopsis)) {
ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(ast_str_buffer(item->synopsis), 1));
char *value = ast_xmldoc_printable(ast_str_buffer(item->synopsis), 1);
ast_cli(a->fd, "%s\n\n", value);
ast_free(value);
}
if (ast_str_strlen(item->description)) {
ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(ast_str_buffer(item->description), 1));
char *value = ast_xmldoc_printable(ast_str_buffer(item->description), 1);
ast_cli(a->fd, "%s\n\n",value);
ast_free(value);
}
tmp = item;
@ -1267,8 +1271,8 @@ static void cli_show_module_type(struct ast_cli_args *a)
{
RAII_VAR(struct ast_xml_doc_item *, item, NULL, ao2_cleanup);
struct ast_xml_doc_item *tmp;
char option_type[64];
int match = 0;
char *synopsis, *since, *description, *syntax, *seealso;
ast_assert(a->argc == 5);
@ -1281,19 +1285,48 @@ static void cli_show_module_type(struct ast_cli_args *a)
while ((tmp = AST_LIST_NEXT(tmp, next))) {
if (!strcasecmp(tmp->type, "configObject") && !strcasecmp(tmp->name, a->argv[4])) {
match = 1;
term_color(option_type, tmp->name, COLOR_MAGENTA, COLOR_BLACK, sizeof(option_type));
ast_cli(a->fd, "%s", option_type);
if (ast_str_strlen(tmp->syntax)) {
ast_cli(a->fd, ": [%s]\n\n", ast_xmldoc_printable(ast_str_buffer(tmp->syntax), 1));
} else {
ast_cli(a->fd, "\n\n");
}
if (ast_str_strlen(tmp->synopsis)) {
ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(ast_str_buffer(tmp->synopsis), 1));
}
if (ast_str_strlen(tmp->description)) {
ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(ast_str_buffer(tmp->description), 1));
synopsis = ast_xmldoc_printable(AS_OR(tmp->synopsis, "Not available"), 1);
since = ast_xmldoc_printable(AS_OR(tmp->since, "Not available"), 1);
description = ast_xmldoc_printable(AS_OR(tmp->description, "Not available"), 1);
syntax = ast_xmldoc_printable(AS_OR(tmp->syntax, "Not available"), 1);
seealso = ast_xmldoc_printable(AS_OR(tmp->seealso, "Not available"), 1);
if (!synopsis || !since || !description || !syntax || !seealso ) {
ast_free(synopsis);
ast_free(since);
ast_free(description);
ast_free(syntax);
ast_free(seealso);
ast_cli(a->fd, "Error: Memory allocation failed\n");
break;
}
ast_cli(a->fd, "\n"
"%s -= Info about Config Object '%s:%s' =- %s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s [%s]\n\n"
COLORIZE_FMT "\n"
"%s\n\n",
ast_term_color(COLOR_MAGENTA, 0), a->argv[3], tmp->name, ast_term_reset(),
COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis,
COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since,
COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description,
COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), tmp->name, syntax,
COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso
);
ast_free(synopsis);
ast_free(since);
ast_free(description);
ast_free(syntax);
ast_free(seealso);
}
}
@ -1304,6 +1337,8 @@ static void cli_show_module_type(struct ast_cli_args *a)
/* Now iterate over the options for the type */
tmp = item;
ast_cli(a->fd, COLORIZE_FMT "\n", COLORIZE(COLOR_MAGENTA, 0, "[Config Options]"));
while ((tmp = AST_LIST_NEXT(tmp, next))) {
if (!strcasecmp(tmp->type, "configOption") && !strcasecmp(tmp->ref, a->argv[4])) {
ast_cli(a->fd, "%-25s -- %-120.120s\n", tmp->name,
@ -1319,8 +1354,8 @@ static void cli_show_module_options(struct ast_cli_args *a)
{
RAII_VAR(struct ast_xml_doc_item *, item, NULL, ao2_cleanup);
struct ast_xml_doc_item *tmp;
char option_name[64];
int match = 0;
char *synopsis, *since, *description, *syntax, *seealso;
ast_assert(a->argc == 6);
@ -1334,21 +1369,48 @@ static void cli_show_module_options(struct ast_cli_args *a)
if (match) {
ast_cli(a->fd, "\n");
}
term_color(option_name, tmp->ref, COLOR_MAGENTA, COLOR_BLACK, sizeof(option_name));
ast_cli(a->fd, "[%s%s]\n", option_name, ast_term_reset());
if (ast_str_strlen(tmp->syntax)) {
ast_cli(a->fd, "%s\n", ast_xmldoc_printable(ast_str_buffer(tmp->syntax), 1));
}
ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(AS_OR(tmp->synopsis, "No information available"), 1));
if (ast_str_strlen(tmp->description)) {
ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(ast_str_buffer(tmp->description), 1));
}
if (ast_str_strlen(tmp->seealso)) {
ast_cli(a->fd, "See Also:\n");
ast_cli(a->fd, "%s\n\n", ast_xmldoc_printable(ast_str_buffer(tmp->seealso), 1));
synopsis = ast_xmldoc_printable(AS_OR(tmp->synopsis, "Not available"), 1);
since = ast_xmldoc_printable(AS_OR(tmp->since, "Not available"), 1);
description = ast_xmldoc_printable(AS_OR(tmp->description, "Not available"), 1);
syntax = ast_xmldoc_printable(AS_OR(tmp->syntax, "Not available"), 1);
seealso = ast_xmldoc_printable(AS_OR(tmp->seealso, "Not available"), 1);
if (!synopsis || !since || !description || !syntax || !seealso ) {
ast_free(synopsis);
ast_free(since);
ast_free(description);
ast_free(syntax);
ast_free(seealso);
ast_cli(a->fd, "Error: Memory allocation failed\n");
break;
}
ast_cli(a->fd, "\n"
"%s -= Info about Config Option '%s:%s:%s' =- %s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n",
ast_term_color(COLOR_MAGENTA, 0), a->argv[3], a->argv[4], tmp->name, ast_term_reset(),
COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis,
COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since,
COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description,
COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax,
COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso
);
ast_free(synopsis);
ast_free(since);
ast_free(description);
ast_free(syntax);
ast_free(seealso);
match = 1;
}
}

@ -1084,10 +1084,6 @@ static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_
int num;
int l;
const char *auth_str;
#ifdef AST_XML_DOCS
char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64];
char arguments_title[64], privilege_title[64], final_response_title[64], list_responses_title[64];
#endif
switch (cmd) {
case CLI_INIT:
@ -1115,18 +1111,6 @@ static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_
authority = ast_str_alloca(MAX_AUTH_PERM_STRING);
#ifdef AST_XML_DOCS
/* setup the titles */
term_color(synopsis_title, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
term_color(description_title, "[Description]\n", COLOR_MAGENTA, 0, 40);
term_color(syntax_title, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
term_color(seealso_title, "[See Also]\n", COLOR_MAGENTA, 0, 40);
term_color(arguments_title, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
term_color(privilege_title, "[Privilege]\n", COLOR_MAGENTA, 0, 40);
term_color(final_response_title, "[Final Response]\n", COLOR_MAGENTA, 0, 40);
term_color(list_responses_title, "[List Responses]\n", COLOR_MAGENTA, 0, 40);
#endif
AST_RWLIST_RDLOCK(&actions);
AST_RWLIST_TRAVERSE(&actions, cur, list) {
for (num = 3; num < a->argc; num++) {
@ -1135,22 +1119,24 @@ static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_
#ifdef AST_XML_DOCS
if (cur->docsrc == AST_XML_DOC) {
char *syntax = ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1);
char *synopsis = ast_xmldoc_printable(S_OR(cur->synopsis, "Not available"), 1);
char *since = ast_xmldoc_printable(S_OR(cur->since, "Not available"), 1);
char *description = ast_xmldoc_printable(S_OR(cur->description, "Not available"), 1);
char *syntax = ast_xmldoc_printable(S_OR(cur->syntax, "Not available"), 1);
char *arguments = ast_xmldoc_printable(S_OR(cur->arguments, "Not available"), 1);
char *seealso = ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1);
char *privilege = ast_xmldoc_printable(S_OR(auth_str, "Not available"), 1);
char *seealso = ast_xmldoc_printable(S_OR(cur->seealso, "Not available"), 1);
char *responses = ast_xmldoc_printable("None", 1);
if (!syntax || !synopsis || !description || !arguments
|| !seealso || !privilege || !responses) {
ast_free(syntax);
if (!synopsis || !since || !description || !syntax || !arguments
|| !privilege || !seealso || !responses) {
ast_free(synopsis);
ast_free(since);
ast_free(description);
ast_free(syntax);
ast_free(arguments);
ast_free(seealso);
ast_free(privilege);
ast_free(seealso);
ast_free(responses);
ast_cli(a->fd, "Allocation failure.\n");
AST_RWLIST_UNLOCK(&actions);
@ -1158,14 +1144,33 @@ static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_
return CLI_FAILURE;
}
ast_cli(a->fd, "%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s",
syntax_title, syntax,
synopsis_title, synopsis,
description_title, description,
arguments_title, arguments,
seealso_title, seealso,
privilege_title, privilege,
list_responses_title);
ast_cli(a->fd, "\n"
"%s -= Info about Manager Command '%s' =- %s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n",
ast_term_color(COLOR_MAGENTA, 0), cur->action, ast_term_reset(),
COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis,
COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since,
COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description,
COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax,
COLORIZE(COLOR_MAGENTA, 0, "[Arguments]"), arguments,
COLORIZE(COLOR_MAGENTA, 0, "[Privilege]"), privilege,
COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso,
COLORIZE(COLOR_MAGENTA, 0, "[List Responses]")
);
if (!cur->list_responses) {
ast_cli(a->fd, "%s\n\n", responses);
@ -1176,22 +1181,33 @@ static char *handle_showmancmd(struct ast_cli_entry *e, int cmd, struct ast_cli_
print_event_instance(a, temp);
}
}
ast_cli(a->fd, "%s", final_response_title);
ast_cli(a->fd,
COLORIZE_FMT "\n",
COLORIZE(COLOR_MAGENTA, 0, "[End List Responses]")
);
ast_cli(a->fd, "\n"
COLORIZE_FMT "\n",
COLORIZE(COLOR_MAGENTA, 0, "[Final Response]")
);
if (!cur->final_response) {
ast_cli(a->fd, "%s\n\n", responses);
} else {
ast_cli(a->fd, "Event: %s\n", cur->final_response->name);
print_event_instance(a, cur->final_response);
}
ast_cli(a->fd,
COLORIZE_FMT "\n",
COLORIZE(COLOR_MAGENTA, 0, "[End Final Response]")
);
ast_free(syntax);
ast_free(synopsis);
ast_free(since);
ast_free(description);
ast_free(syntax);
ast_free(arguments);
ast_free(seealso);
ast_free(privilege);
ast_free(seealso);
ast_free(responses);
} else
#endif
@ -7754,6 +7770,11 @@ int ast_manager_register2(const char *action, int auth, int (*func)(struct manse
return -1;
}
if (ast_string_field_init_extended(cur, since)) {
ao2_t_ref(cur, -1, "action object creation failed");
return -1;
}
cur->action = action;
cur->authority = auth;
cur->func = func;
@ -7762,6 +7783,10 @@ int ast_manager_register2(const char *action, int auth, int (*func)(struct manse
if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
char *tmpxml;
tmpxml = ast_xmldoc_build_since("manager", action, NULL);
ast_string_field_set(cur, since, tmpxml);
ast_free(tmpxml);
tmpxml = ast_xmldoc_build_synopsis("manager", action, NULL);
ast_string_field_set(cur, synopsis, tmpxml);
ast_free(tmpxml);
@ -9174,39 +9199,50 @@ static char *handle_manager_show_events(struct ast_cli_entry *e, int cmd, struct
static void print_event_instance(struct ast_cli_args *a, struct ast_xml_doc_item *instance)
{
char syntax_title[64], description_title[64], synopsis_title[64], seealso_title[64], arguments_title[64];
term_color(synopsis_title, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
term_color(description_title, "[Description]\n", COLOR_MAGENTA, 0, 40);
term_color(syntax_title, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
term_color(seealso_title, "[See Also]\n", COLOR_MAGENTA, 0, 40);
term_color(arguments_title, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
if (!ast_strlen_zero(ast_str_buffer(instance->synopsis))) {
char *synopsis = ast_xmldoc_printable(ast_str_buffer(instance->synopsis), 1);
ast_cli(a->fd, "%s%s\n\n", synopsis_title, synopsis);
ast_free(synopsis);
}
if (!ast_strlen_zero(ast_str_buffer(instance->syntax))) {
char *syntax = ast_xmldoc_printable(ast_str_buffer(instance->syntax), 1);
ast_cli(a->fd, "%s%s\n\n", syntax_title, syntax);
ast_free(syntax);
}
if (!ast_strlen_zero(ast_str_buffer(instance->description))) {
char *description = ast_xmldoc_printable(ast_str_buffer(instance->description), 1);
ast_cli(a->fd, "%s%s\n\n", description_title, description);
ast_free(description);
}
if (!ast_strlen_zero(ast_str_buffer(instance->arguments))) {
char *arguments = ast_xmldoc_printable(ast_str_buffer(instance->arguments), 1);
ast_cli(a->fd, "%s%s\n\n", arguments_title, arguments);
ast_free(arguments);
}
if (!ast_strlen_zero(ast_str_buffer(instance->seealso))) {
char *seealso = ast_xmldoc_printable(ast_str_buffer(instance->seealso), 1);
ast_cli(a->fd, "%s%s\n\n", seealso_title, seealso);
ast_free(seealso);
}
char *since, *syntax, *description, *synopsis, *seealso, *arguments;
synopsis = ast_xmldoc_printable(AS_OR(instance->synopsis, "Not available"), 1);
since = ast_xmldoc_printable(AS_OR(instance->since, "Not available"), 1);
description = ast_xmldoc_printable(AS_OR(instance->description, "Not available"), 1);
syntax = ast_xmldoc_printable(AS_OR(instance->syntax, "Not available"), 1);
arguments = ast_xmldoc_printable(AS_OR(instance->arguments, "Not available"), 1);
seealso = ast_xmldoc_printable(AS_OR(instance->seealso, "Not available"), 1);
if (!synopsis || !since || !description || !syntax || !arguments || !seealso) {
ast_cli(a->fd, "Error: Memory allocation failed\n");
goto free_docs;
}
ast_cli(a->fd, "\n"
"%s -= Info about Manager Event '%s' =- %s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n",
ast_term_color(COLOR_MAGENTA, 0), instance->name, ast_term_reset(),
COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis,
COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since,
COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description,
COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax,
COLORIZE(COLOR_MAGENTA, 0, "[Arguments]"), arguments,
COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso
);
free_docs:
ast_free(synopsis);
ast_free(since);
ast_free(description);
ast_free(syntax);
ast_free(arguments);
ast_free(seealso);
}
static char *handle_manager_show_event(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)

@ -46,6 +46,7 @@ struct ast_app {
int (*execute)(struct ast_channel *chan, const char *data);
AST_DECLARE_STRING_FIELDS(
AST_STRING_FIELD(synopsis); /*!< Synopsis text for 'show applications' */
AST_STRING_FIELD(since); /*!< Since text for 'show applications' */
AST_STRING_FIELD(description); /*!< Description (help text) for 'show application &lt;name&gt;' */
AST_STRING_FIELD(syntax); /*!< Syntax text for 'core show applications' */
AST_STRING_FIELD(arguments); /*!< Arguments description */
@ -142,6 +143,11 @@ int ast_register_application2(const char *app, int (*execute)(struct ast_channel
ast_string_field_set(tmp, synopsis, tmpxml);
ast_free(tmpxml);
/* load since */
tmpxml = ast_xmldoc_build_since("application", app, ast_module_name(tmp->module));
ast_string_field_set(tmp, since, tmpxml);
ast_free(tmpxml);
/* load description */
tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module));
ast_string_field_set(tmp, description, tmpxml);
@ -191,67 +197,61 @@ int ast_register_application2(const char *app, int (*execute)(struct ast_channel
static void print_app_docs(struct ast_app *aa, int fd)
{
char *synopsis = NULL, *since = NULL, *description = NULL, *syntax = NULL, *arguments = NULL, *seealso = NULL;
#ifdef AST_XML_DOCS
char *synopsis = NULL, *description = NULL, *arguments = NULL, *seealso = NULL;
if (aa->docsrc == AST_XML_DOC) {
synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1);
since = ast_xmldoc_printable(S_OR(aa->since, "Not available"), 1);
description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1);
syntax = ast_xmldoc_printable(S_OR(aa->syntax, "Not available"), 1);
arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1);
seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1);
if (!synopsis || !description || !arguments || !seealso) {
goto free_docs;
}
ast_cli(fd, "\n"
"%s -= Info about application '%s' =- %s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s%s%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n",
ast_term_color(COLOR_MAGENTA, 0), aa->name, ast_term_reset(),
COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis,
COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description,
COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"),
ast_term_color(COLOR_CYAN, 0), S_OR(aa->syntax, "Not available"), ast_term_reset(),
COLORIZE(COLOR_MAGENTA, 0, "[Arguments]"), arguments,
COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso);
free_docs:
ast_free(synopsis);
ast_free(description);
ast_free(arguments);
ast_free(seealso);
} else
#endif
{
ast_cli(fd, "\n"
"%s -= Info about application '%s' =- %s\n\n"
COLORIZE_FMT "\n"
COLORIZE_FMT "\n\n"
COLORIZE_FMT "\n"
COLORIZE_FMT "\n\n"
COLORIZE_FMT "\n"
COLORIZE_FMT "\n\n"
COLORIZE_FMT "\n"
COLORIZE_FMT "\n\n"
COLORIZE_FMT "\n"
COLORIZE_FMT "\n",
ast_term_color(COLOR_MAGENTA, 0), aa->name, ast_term_reset(),
COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"),
COLORIZE(COLOR_CYAN, 0, S_OR(aa->synopsis, "Not available")),
COLORIZE(COLOR_MAGENTA, 0, "[Description]"),
COLORIZE(COLOR_CYAN, 0, S_OR(aa->description, "Not available")),
COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"),
COLORIZE(COLOR_CYAN, 0, S_OR(aa->syntax, "Not available")),
COLORIZE(COLOR_MAGENTA, 0, "[Arguments]"),
COLORIZE(COLOR_CYAN, 0, S_OR(aa->arguments, "Not available")),
COLORIZE(COLOR_MAGENTA, 0, "[See Also]"),
COLORIZE(COLOR_CYAN, 0, S_OR(aa->seealso, "Not available")));
synopsis = ast_strdup(S_OR(aa->synopsis, "Not Available"));
since = ast_strdup(S_OR(aa->since, "Not Available"));
description = ast_strdup(S_OR(aa->description, "Not Available"));
syntax = ast_strdup(S_OR(aa->syntax, "Not Available"));
arguments = ast_strdup(S_OR(aa->arguments, "Not Available"));
seealso = ast_strdup(S_OR(aa->seealso, "Not Available"));
}
/* check allocated memory. */
if (!synopsis || !since || !description || !syntax || !arguments || !seealso) {
goto free_docs;
}
ast_cli(fd, "\n"
"%s -= Info about Application '%s' =- %s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n",
ast_term_color(COLOR_MAGENTA, 0), aa->name, ast_term_reset(),
COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis,
COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since,
COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description,
COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax,
COLORIZE(COLOR_MAGENTA, 0, "[Arguments]"), arguments,
COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso
);
free_docs:
ast_free(synopsis);
ast_free(since);
ast_free(description);
ast_free(syntax);
ast_free(arguments);
ast_free(seealso);
}
/*!

@ -144,10 +144,8 @@ static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_c
{
struct ast_custom_function *acf;
/* Maximum number of characters added by terminal coloring is 22 */
char infotitle[64 + AST_MAX_APP + 22], syntitle[40], desctitle[40], argtitle[40], seealsotitle[40];
char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL;
char stxtitle[40], *syntax = NULL, *arguments = NULL;
int syntax_size, description_size, synopsis_size, arguments_size, seealso_size;
char *synopsis = NULL, *since = NULL, *description = NULL, *syntax = NULL, *arguments = NULL, *seealso = NULL;
char *rtn = CLI_SUCCESS;
switch (cmd) {
case CLI_INIT:
@ -170,71 +168,62 @@ static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_c
return CLI_FAILURE;
}
syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
syntax = ast_malloc(syntax_size);
if (!syntax) {
ast_cli(a->fd, "Memory allocation failure!\n");
return CLI_FAILURE;
}
snprintf(info, sizeof(info), "\n -= Info about function '%s' =- \n\n", acf->name);
term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
term_color(desctitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
#ifdef AST_XML_DOCS
if (acf->docsrc == AST_XML_DOC) {
arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1);
synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1);
since = ast_xmldoc_printable(S_OR(acf->since, "Not available"), 1);
description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1);
syntax = ast_xmldoc_printable(S_OR(acf->syntax, "Not available"), 1);
arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1);
seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1);
} else
#endif
{
synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
synopsis = ast_malloc(synopsis_size);
description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
description = ast_malloc(description_size);
arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
arguments = ast_malloc(arguments_size);
seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
seealso = ast_malloc(seealso_size);
/* check allocated memory. */
if (!synopsis || !description || !arguments || !seealso) {
ast_free(synopsis);
ast_free(description);
ast_free(arguments);
ast_free(seealso);
ast_free(syntax);
return CLI_FAILURE;
}
term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size);
term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
synopsis = ast_strdup(S_OR(acf->synopsis, "Not Available"));
since = ast_strdup(S_OR(acf->since, "Not Available"));
description = ast_strdup(S_OR(acf->desc, "Not Available"));
syntax = ast_strdup(S_OR(acf->syntax, "Not Available"));
arguments = ast_strdup(S_OR(acf->arguments, "Not Available"));
seealso = ast_strdup(S_OR(acf->seealso, "Not Available"));
}
ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
infotitle, syntitle, synopsis, desctitle, description,
stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
ast_free(arguments);
/* check allocated memory. */
if (!synopsis || !since || !description || !syntax || !arguments || !seealso) {
rtn = CLI_FAILURE;
goto free_docs;
}
ast_cli(a->fd, "\n"
"%s -= Info about Function '%s' =- %s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n",
ast_term_color(COLOR_MAGENTA, 0), acf->name, ast_term_reset(),
COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis,
COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since,
COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description,
COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax,
COLORIZE(COLOR_MAGENTA, 0, "[Arguments]"), arguments,
COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso
);
free_docs:
ast_free(synopsis);
ast_free(since);
ast_free(description);
ast_free(seealso);
ast_free(syntax);
ast_free(arguments);
ast_free(seealso);
return CLI_SUCCESS;
return rtn;
}
static struct ast_custom_function *ast_custom_function_find_nolock(const char *name)
@ -339,11 +328,21 @@ static int acf_retrieve_docs(struct ast_custom_function *acf)
return -1;
}
if (ast_string_field_init_extended(acf, since)) {
ast_string_field_free_memory(acf);
return -1;
}
/* load synopsis */
tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod));
ast_string_field_set(acf, synopsis, tmpxml);
ast_free(tmpxml);
/* load since */
tmpxml = ast_xmldoc_build_since("function", acf->name, ast_module_name(acf->mod));
ast_string_field_set(acf, since, tmpxml);
ast_free(tmpxml);
/* load description */
tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod));
ast_string_field_set(acf, desc, tmpxml);

@ -1722,6 +1722,91 @@ char *ast_xmldoc_build_seealso(const char *type, const char *name, const char *m
return output;
}
/*!
* \internal
* \brief Build since information for an item
*
* \param node The since node to parse
*
* \note This method exists for when you already have the node. This
* prevents having to lock the documentation tree twice
*
* \retval A malloc'd character pointer to the since information of the item
* \retval NULL on failure
*
* \since 22
*/
static char *_ast_xmldoc_build_since(struct ast_xml_node *node)
{
char *output;
struct ast_str *outputstr;
const char *content;
int first = 1;
/* Find the <since> node. */
for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
if (!strcasecmp(ast_xml_node_get_name(node), "since")) {
break;
}
}
if (!node || !ast_xml_node_get_children(node)) {
/* we couldnt find a <since> node. */
return NULL;
}
/* prepare the output string. */
outputstr = ast_str_create(128);
if (!outputstr) {
return NULL;
}
/* get into the <since> node. */
for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
if (strcasecmp(ast_xml_node_get_name(node), "version")) {
continue;
}
content = ast_xml_get_text(node);
if (!content) {
continue;
}
ast_str_append(&outputstr, 0, "%s%s", (first ? "" : ", "), content);
first = 0;
ast_xml_free_text(content);
}
output = ast_strdup(ast_str_buffer(outputstr));
ast_free(outputstr);
return output;
}
char *ast_xmldoc_build_since(const char *type, const char *name, const char *module)
{
char *output;
struct ast_xml_node *node;
if (ast_strlen_zero(type) || ast_strlen_zero(name)) {
return NULL;
}
/* get the application/function root node. */
AST_RWLIST_RDLOCK(&xmldoc_tree);
node = xmldoc_get_node(type, name, module, documentation_language);
if (!node || !ast_xml_node_get_children(node)) {
AST_RWLIST_UNLOCK(&xmldoc_tree);
return NULL;
}
output = _ast_xmldoc_build_since(node);
AST_RWLIST_UNLOCK(&xmldoc_tree);
return output;
}
/*!
* \internal
* \brief Parse a \<enum\> node.
@ -2286,11 +2371,12 @@ static void ast_xml_doc_item_destructor(void *obj)
return;
}
ast_free(doc->syntax);
ast_free(doc->seealso);
ast_free(doc->arguments);
ast_free(doc->synopsis);
ast_free(doc->since);
ast_free(doc->description);
ast_free(doc->syntax);
ast_free(doc->arguments);
ast_free(doc->seealso);
ast_string_field_free_memory(doc);
if (AST_LIST_NEXT(doc, next)) {
@ -2318,11 +2404,13 @@ static struct ast_xml_doc_item *ast_xml_doc_item_alloc(const char *name, const c
return NULL;
}
if ( !(item->syntax = ast_str_create(128))
|| !(item->seealso = ast_str_create(128))
if ( !(item->synopsis = ast_str_create(128))
|| !(item->since = ast_str_create(128))
|| !(item->description = ast_str_create(128))
|| !(item->syntax = ast_str_create(128))
|| !(item->arguments = ast_str_create(128))
|| !(item->synopsis = ast_str_create(128))
|| !(item->description = ast_str_create(128))) {
|| !(item->seealso = ast_str_create(128))
) {
ast_log(AST_LOG_ERROR, "Failed to allocate strings for ast_xml_doc_item instance\n");
goto ast_xml_doc_item_failure;
}
@ -2381,44 +2469,50 @@ static int ast_xml_doc_item_cmp(void *obj, void *arg, int flags)
static struct ast_xml_doc_item *xmldoc_build_documentation_item(struct ast_xml_node *node, const char *name, const char *type)
{
struct ast_xml_doc_item *item;
char *syntax;
char *seealso;
char *arguments;
char *synopsis;
char *since;
char *description;
char *syntax;
char *arguments;
char *seealso;
if (!(item = ast_xml_doc_item_alloc(name, type))) {
return NULL;
}
item->node = node;
syntax = _ast_xmldoc_build_syntax(node, type, name);
seealso = _ast_xmldoc_build_seealso(node);
arguments = _ast_xmldoc_build_arguments(node);
synopsis = _ast_xmldoc_build_synopsis(node);
since = _ast_xmldoc_build_since(node);
description = _ast_xmldoc_build_description(node);
syntax = _ast_xmldoc_build_syntax(node, type, name);
arguments = _ast_xmldoc_build_arguments(node);
seealso = _ast_xmldoc_build_seealso(node);
if (synopsis) {
ast_str_set(&item->synopsis, 0, "%s", synopsis);
}
if (since) {
ast_str_set(&item->since, 0, "%s", since);
}
if (description) {
ast_str_set(&item->description, 0, "%s", description);
}
if (syntax) {
ast_str_set(&item->syntax, 0, "%s", syntax);
}
if (seealso) {
ast_str_set(&item->seealso, 0, "%s", seealso);
}
if (arguments) {
ast_str_set(&item->arguments, 0, "%s", arguments);
}
if (synopsis) {
ast_str_set(&item->synopsis, 0, "%s", synopsis);
}
if (description) {
ast_str_set(&item->description, 0, "%s", description);
if (seealso) {
ast_str_set(&item->seealso, 0, "%s", seealso);
}
ast_free(syntax);
ast_free(seealso);
ast_free(arguments);
ast_free(synopsis);
ast_free(since);
ast_free(description);
ast_free(syntax);
ast_free(arguments);
ast_free(seealso);
return item;
}

@ -3834,8 +3834,10 @@ int AST_OPTIONAL_API_NAME(ast_agi_register)(struct ast_module *mod, agi_command
if (ast_strlen_zero(cmd->summary) && ast_strlen_zero(cmd->usage)) {
#ifdef AST_XML_DOCS
*((char **) &cmd->summary) = ast_xmldoc_build_synopsis("agi", fullcmd, NULL);
*((char **) &cmd->since) = ast_xmldoc_build_since("agi", fullcmd, NULL);
*((char **) &cmd->usage) = ast_xmldoc_build_description("agi", fullcmd, NULL);
*((char **) &cmd->syntax) = ast_xmldoc_build_syntax("agi", fullcmd, NULL);
*((char **) &cmd->arguments) = ast_xmldoc_build_arguments("agi", fullcmd, NULL);
*((char **) &cmd->seealso) = ast_xmldoc_build_seealso("agi", fullcmd, NULL);
*((enum ast_doc_src *) &cmd->docsrc) = AST_XML_DOC;
#endif
@ -3882,12 +3884,16 @@ int AST_OPTIONAL_API_NAME(ast_agi_unregister)(agi_command *cmd)
#ifdef AST_XML_DOCS
if (e->docsrc == AST_XML_DOC) {
ast_free((char *) e->summary);
ast_free((char *) e->since);
ast_free((char *) e->usage);
ast_free((char *) e->syntax);
ast_free((char *) e->arguments);
ast_free((char *) e->seealso);
*((char **) &e->summary) = NULL;
*((char **) &e->since) = NULL;
*((char **) &e->usage) = NULL;
*((char **) &e->syntax) = NULL;
*((char **) &e->arguments) = NULL;
*((char **) &e->seealso) = NULL;
}
#endif
@ -4346,72 +4352,66 @@ static char *handle_cli_agi_show(struct ast_cli_entry *e, int cmd, struct ast_cl
if (a->argc > e->args - 1) {
command = find_command(a->argv + e->args, 1);
if (command) {
char *synopsis = NULL, *description = NULL, *syntax = NULL, *seealso = NULL;
char info[30 + MAX_CMD_LEN]; /* '-= Info about...' */
char infotitle[30 + MAX_CMD_LEN + AST_TERM_MAX_ESCAPE_CHARS]; /* '-= Info about...' with colors */
char syntitle[11 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Syntax]\n with colors */
char desctitle[15 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Description]\n with colors */
char deadtitle[13 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Runs Dead]\n with colors */
char deadcontent[3 + AST_TERM_MAX_ESCAPE_CHARS]; /* 'Yes' or 'No' with colors */
char seealsotitle[12 + AST_TERM_MAX_ESCAPE_CHARS]; /* [See Also]\n with colors */
char stxtitle[10 + AST_TERM_MAX_ESCAPE_CHARS]; /* [Syntax]\n with colors */
size_t synlen, desclen, seealsolen, stxlen;
term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, sizeof(syntitle));
term_color(desctitle, "[Description]\n", COLOR_MAGENTA, 0, sizeof(desctitle));
term_color(deadtitle, "[Runs Dead]\n", COLOR_MAGENTA, 0, sizeof(deadtitle));
term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, sizeof(seealsotitle));
term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, sizeof(stxtitle));
term_color(deadcontent, command->dead ? "Yes" : "No", COLOR_CYAN, 0, sizeof(deadcontent));
char *synopsis = NULL, *since = NULL, *description = NULL, *syntax = NULL, *arguments = NULL, *seealso = NULL;
ast_join(fullcmd, sizeof(fullcmd), a->argv + e->args);
snprintf(info, sizeof(info), "\n -= Info about agi '%s' =- ", fullcmd);
term_color(infotitle, info, COLOR_CYAN, 0, sizeof(infotitle));
#ifdef AST_XML_DOCS
if (command->docsrc == AST_XML_DOC) {
synopsis = ast_xmldoc_printable(S_OR(command->summary, "Not available"), 1);
since = ast_xmldoc_printable(S_OR(command->since, "Not available"), 1);
description = ast_xmldoc_printable(S_OR(command->usage, "Not available"), 1);
syntax = ast_xmldoc_printable(S_OR(command->syntax, "Not available"), 1);
arguments = ast_xmldoc_printable(S_OR(command->arguments, "Not available"), 1);
seealso = ast_xmldoc_printable(S_OR(command->seealso, "Not available"), 1);
if (!seealso || !description || !synopsis) {
error = 1;
goto return_cleanup;
}
} else
#endif
{
synlen = strlen(S_OR(command->summary, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
synopsis = ast_malloc(synlen);
desclen = strlen(S_OR(command->usage, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
description = ast_malloc(desclen);
seealsolen = strlen(S_OR(command->seealso, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
seealso = ast_malloc(seealsolen);
if (!synopsis || !description || !seealso) {
error = 1;
goto return_cleanup;
}
term_color(synopsis, S_OR(command->summary, "Not available"), COLOR_CYAN, 0, synlen);
term_color(description, S_OR(command->usage, "Not available"), COLOR_CYAN, 0, desclen);
term_color(seealso, S_OR(command->seealso, "Not available"), COLOR_CYAN, 0, seealsolen);
synopsis = ast_strdup(S_OR(command->summary, "Not Available"));
since = ast_strdup(S_OR(command->since, "Not Available"));
description = ast_strdup(S_OR(command->usage, "Not Available"));
syntax = ast_strdup(S_OR(command->syntax, "Not Available"));
arguments = ast_strdup(S_OR(command->arguments, "Not Available"));
seealso = ast_strdup(S_OR(command->seealso, "Not Available"));
}
stxlen = strlen(S_OR(command->syntax, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
syntax = ast_malloc(stxlen);
if (!syntax) {
if (!synopsis || !since || !description || !syntax || !arguments || !seealso) {
error = 1;
goto return_cleanup;
}
term_color(syntax, S_OR(command->syntax, "Not available"), COLOR_CYAN, 0, stxlen);
ast_cli(a->fd, "%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n", infotitle, stxtitle, syntax,
desctitle, description, syntitle, synopsis, deadtitle, deadcontent,
seealsotitle, seealso);
ast_cli(a->fd, "\n"
"%s -= Info about AGI '%s' =- %s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n"
COLORIZE_FMT "\n"
"%s\n\n",
ast_term_color(COLOR_MAGENTA, 0), fullcmd, ast_term_reset(),
COLORIZE(COLOR_MAGENTA, 0, "[Synopsis]"), synopsis,
COLORIZE(COLOR_MAGENTA, 0, "[Since]"), since,
COLORIZE(COLOR_MAGENTA, 0, "[Description]"), description,
COLORIZE(COLOR_MAGENTA, 0, "[Syntax]"), syntax,
COLORIZE(COLOR_MAGENTA, 0, "[Arguments]"), arguments,
COLORIZE(COLOR_MAGENTA, 0, "[Runs Dead]"), command->dead ? "Yes" : "No",
COLORIZE(COLOR_MAGENTA, 0, "[See Also]"), seealso
);
return_cleanup:
ast_free(synopsis);
ast_free(since);
ast_free(description);
ast_free(syntax);
ast_free(arguments);
ast_free(seealso);
} else {
if (find_command(a->argv + e->args, -1)) {

@ -1,11 +1,14 @@
{{#api_declaration}}
# {{name_title}}
{{#since}}
## Since: {{since}}
{{/since}}
| Method | Path (Parameters are case-sensitive) | Return Model | Summary |
|:------ |:------------------------------------ |:------------ |:------- |
| Method | Path (Parameters are case-sensitive) | Return Model | Summary | Since |
|:------ |:------------------------------------ |:------------ |:------- |:----- |
{{#apis}}
{{#operations}}
| {{http_method}} | [{{wiki_path}}](#{{nickname_lc}}) | {{#response_class}}{{#is_primitive}}{{name}}{{/is_primitive}}{{^is_primitive}}[{{wiki_name}}]({{wiki_prefix}}Asterisk_REST_Data_Models#{{lc_singular_name}}){{/is_primitive}}{{/response_class}} | {{{summary}}} |
| {{http_method}} | [{{wiki_path}}](#{{nickname_lc}}) | {{#response_class}}{{#is_primitive}}{{name}}{{/is_primitive}}{{^is_primitive}}[{{wiki_name}}]({{wiki_prefix}}Asterisk_REST_Data_Models#{{lc_singular_name}}){{/is_primitive}}{{/response_class}} | {{{summary}}} | {{since}} |
{{/operations}}
{{/apis}}
{{#apis}}
@ -14,6 +17,9 @@
---
[//]: # (anchor:{{nickname_lc}})
## {{nickname}}
{{#since}}
### Since: {{since}}
{{/since}}
### {{http_method}} {{wiki_path}}
{{{wiki_summary}}}{{#wiki_notes}} {{{wiki_notes}}}{{/wiki_notes}}
{{#has_path_parameters}}

@ -373,6 +373,7 @@ class Operation(Stringify):
self.summary = None
self.notes = None
self.error_responses = []
self.since = []
def load(self, op_json, processor, context):
context = context.next_stack(op_json, 'nickname')
@ -383,6 +384,8 @@ class Operation(Stringify):
response_class = op_json.get('responseClass')
self.response_class = response_class and SwaggerType().load(
response_class, processor, context)
since = op_json.get('since') or []
self.since = ", ".join(since)
# Specifying WebSocket URL's is our own extension
self.is_websocket = op_json.get('upgrade') == 'websocket'
@ -611,6 +614,7 @@ class ApiDeclaration(Stringify):
self.api_version = None
self.base_path = None
self.resource_path = None
self.since = []
self.apis = []
self.models = []
@ -658,6 +662,8 @@ class ApiDeclaration(Stringify):
self.base_path = api_decl_json.get('basePath')
self.resource_path = api_decl_json.get('resourcePath')
self.requires_modules = api_decl_json.get('requiresModules') or []
since = api_decl_json.get('since') or []
self.since = ", ".join(since)
api_json = api_decl_json.get('apis') or []
self.apis = [
Api().load(j, processor, context) for j in api_json]

Loading…
Cancel
Save