xmldocs: Add support for an <example> tag in the Asterisk XML Documentation

This patch adds support for an <example /> tag in the XML documentation schema.

For CLI help, this doesn't change the formatting too much:
 - Preceeding white space is removed
 - Unlike with para elements, new lines are preserved

However, having an <example /> tag in the XML schema allows for the wiki
documentation generation script to surround the documentation with {code} or
{noformat} tags, generating much better content for the wiki - and allowing us
to put dialplan examples (and other code snippets, if desired) into the
documentation for an application/function/AMI command/etc.

Review: https://reviewboard.asterisk.org/r/3807/


git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419822 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
Matthew Jordan
2014-07-31 11:49:40 +00:00
parent 485d0379ae
commit 922e3203a9
3 changed files with 103 additions and 18 deletions

View File

@@ -92,7 +92,7 @@
<!ELEMENT configOptionToEnum (configOption|xi:include)*> <!ELEMENT configOptionToEnum (configOption|xi:include)*>
<!ATTLIST configOptionToEnum prefix CDATA ""> <!ATTLIST configOptionToEnum prefix CDATA "">
<!ELEMENT description (para|note|warning|variablelist|enumlist|info|xi:include)*> <!ELEMENT description (para|note|warning|variablelist|enumlist|info|example|xi:include)*>
<!ELEMENT parameter (optionlist|enumlist|argument|para|note|warning|parameter|info|xi:include)*> <!ELEMENT parameter (optionlist|enumlist|argument|para|note|warning|parameter|info|xi:include)*>
<!ATTLIST parameter name CDATA ""> <!ATTLIST parameter name CDATA "">
@@ -129,6 +129,10 @@
<!ELEMENT directory (#PCDATA)> <!ELEMENT directory (#PCDATA)>
<!ELEMENT astcli (#PCDATA)> <!ELEMENT astcli (#PCDATA)>
<!ELEMENT example (#PCDATA|xi:include)*>
<!ATTLIST example title CDATA "">
<!ATTLIST example language CDATA "" >
<!ELEMENT note (para+|xi:include*)> <!ELEMENT note (para+|xi:include*)>
<!ELEMENT warning (para+|xi:include*)> <!ELEMENT warning (para+|xi:include*)>

View File

@@ -66,13 +66,25 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
<para>target_extra: Defaults to 40ms</para> <para>target_extra: Defaults to 40ms</para>
<para>This option only affects the adaptive jitterbuffer. It represents the amount time in milliseconds by which the new jitter buffer will pad its size.</para> <para>This option only affects the adaptive jitterbuffer. It represents the amount time in milliseconds by which the new jitter buffer will pad its size.</para>
<para> </para> <para> </para>
<para>Examples:</para> <example title="Fixed with defaults" language="text">
<para>exten => 1,1,Set(JITTERBUFFER(fixed)=default);Fixed with defaults. </para> exten => 1,1,Set(JITTERBUFFER(fixed)=default)
<para>exten => 1,1,Set(JITTERBUFFER(fixed)=200);Fixed with max size 200ms, default resync threshold and target extra. </para> </example>
<para>exten => 1,1,Set(JITTERBUFFER(fixed)=200,1500);Fixed with max size 200ms resync threshold 1500. </para> <example title="Fixed with 200ms max size" language="text">
<para>exten => 1,1,Set(JITTERBUFFER(adaptive)=default);Adaptive with defaults. </para> exten => 1,1,Set(JITTERBUFFER(fixed)=200)
<para>exten => 1,1,Set(JITTERBUFFER(adaptive)=200,,60);Adaptive with max size 200ms, default resync threshold and 40ms target extra. </para> </example>
<para>exten => 1,n,Set(JITTERBUFFER(disabled)=);Remove previously applied jitterbuffer </para> <example title="Fixed with 200ms max size, resync threshold 1500" language="text">
exten => 1,1,Set(JITTERBUFFER(fixed)=200,1500)
</example>
<example title="Adaptive with defaults" language="text">
exten => 1,1,Set(JITTERBUFFER(adaptive)=default)
</example>
<example title="Adaptive with 200ms max size, 60ms target extra" language="text">
exten => 1,1,Set(JITTERBUFFER(adaptive)=200,,60)
</example>
<example title="Set a fixed jitterbuffer with defaults; then remove it" language="text">
exten => 1,1,Set(JITTERBUFFER(fixed)=default)
exten => 1,n,Set(JITTERBUFFER(disabled)=)
</example>
<note><para>If a channel specifies a jitterbuffer due to channel driver configuration and <note><para>If a channel specifies a jitterbuffer due to channel driver configuration and
the JITTERBUFFER function has set a jitterbuffer for that channel, the jitterbuffer set by the JITTERBUFFER function has set a jitterbuffer for that channel, the jitterbuffer set by
the JITTERBUFFER function will take priority and the jitterbuffer set by the channel the JITTERBUFFER function will take priority and the jitterbuffer set by the channel

View File

@@ -104,7 +104,9 @@ static const struct strcolorized_tags {
/* Special tags */ /* Special tags */
{ "", "", COLOR_YELLOW, "<note>", "</note>" }, { "", "", COLOR_YELLOW, "<note>", "</note>" },
{ "", "", COLOR_RED, "<warning>", "</warning>" } { "", "", COLOR_RED, "<warning>", "</warning>" },
{ "", "", COLOR_WHITE, "<example>", "</example>" },
{ "", "", COLOR_GRAY, "<exampletext>", "</exampletext>"},
}; };
static const struct strspecial_tags { static const struct strspecial_tags {
@@ -113,7 +115,8 @@ static const struct strspecial_tags {
const char *end; /*!< Print this at the end. */ const char *end; /*!< Print this at the end. */
} special_tags[] = { } special_tags[] = {
{ "note", "<note>NOTE:</note> ", "" }, { "note", "<note>NOTE:</note> ", "" },
{ "warning", "<warning>WARNING!!!:</warning> ", "" } { "warning", "<warning>WARNING!!!:</warning> ", "" },
{ "example", "<example>Example:</example> ", "" },
}; };
/*! /*!
@@ -453,8 +456,9 @@ char *ast_xmldoc_printable(const char *bwinput, int withcolors)
* \param text String to be cleaned up. * \param text String to be cleaned up.
* \param output buffer (not already allocated). * \param output buffer (not already allocated).
* \param lastspaces Remove last spaces in the string. * \param lastspaces Remove last spaces in the string.
* \param maintain_newlines Preserve new line characters (\n \r) discovered in the string
*/ */
static void xmldoc_string_cleanup(const char *text, struct ast_str **output, int lastspaces) static void xmldoc_string_cleanup(const char *text, struct ast_str **output, int lastspaces, int maintain_newlines)
{ {
int i; int i;
size_t textlen; size_t textlen;
@@ -474,6 +478,9 @@ static void xmldoc_string_cleanup(const char *text, struct ast_str **output, int
for (i = 0; i < textlen; i++) { for (i = 0; i < textlen; i++) {
if (text[i] == '\n' || text[i] == '\r') { if (text[i] == '\n' || text[i] == '\r') {
if (maintain_newlines) {
ast_str_append(output, 0, "%c", text[i]);
}
/* remove spaces/tabs/\n after a \n. */ /* remove spaces/tabs/\n after a \n. */
while (text[i + 1] == '\t' || text[i + 1] == '\r' || text[i + 1] == '\n') { while (text[i + 1] == '\t' || text[i + 1] == '\r' || text[i + 1] == '\n') {
i++; i++;
@@ -1417,7 +1424,7 @@ static int xmldoc_parse_para(struct ast_xml_node *node, const char *tabs, const
tmptext = ast_xml_get_text(tmp); tmptext = ast_xml_get_text(tmp);
if (tmptext) { if (tmptext) {
/* Strip \n etc. */ /* Strip \n etc. */
xmldoc_string_cleanup(tmptext, &tmpstr, 0); xmldoc_string_cleanup(tmptext, &tmpstr, 0, 0);
ast_xml_free_text(tmptext); ast_xml_free_text(tmptext);
if (tmpstr) { if (tmpstr) {
if (strcasecmp(ast_xml_node_get_name(tmp), "text")) { if (strcasecmp(ast_xml_node_get_name(tmp), "text")) {
@@ -1437,6 +1444,57 @@ static int xmldoc_parse_para(struct ast_xml_node *node, const char *tabs, const
return ret; return ret;
} }
/*!
* \internal
* \brief Parse an <example> node.
* \since 13.0.0
*
* \param fixnode An ast xml pointer to the <example> node.
* \param buffer The output buffer.
*
* \retval 0 if no example node is parsed.
* \retval 1 if an example node is parsed.
*/
static int xmldoc_parse_example(struct ast_xml_node *fixnode, struct ast_str **buffer)
{
struct ast_xml_node *node = fixnode;
const char *tmptext;
const char *title;
struct ast_str *stripped_text;
int ret = 0;
if (!node || !ast_xml_node_get_children(node)) {
return ret;
}
if (strcasecmp(ast_xml_node_get_name(node), "example")) {
return ret;
}
ret = 1;
title = ast_xml_get_attribute(node, "title");
if (title) {
ast_str_append(buffer, 0, "%s", title);
ast_xml_free_attr(title);
}
ast_str_append(buffer, 0, "\n");
for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
tmptext = ast_xml_get_text(node);
if (tmptext) {
xmldoc_string_cleanup(tmptext, &stripped_text, 0, 1);
if (stripped_text) {
ast_str_append(buffer, 0, "<exampletext>%s</exampletext>\n", ast_str_buffer(stripped_text));
ast_xml_free_text(tmptext);
ast_free(stripped_text);
}
}
}
return ret;
}
/*! /*!
* \internal * \internal
* \brief Parse special elements defined in 'struct special_tags' special elements must have a <para> element inside them. * \brief Parse special elements defined in 'struct special_tags' special elements must have a <para> element inside them.
@@ -1472,6 +1530,11 @@ static int xmldoc_parse_specialtags(struct ast_xml_node *fixnode, const char *ta
ast_str_append(buffer, 0, "%s%s", tabs, special_tags[i].init); ast_str_append(buffer, 0, "%s%s", tabs, special_tags[i].init);
} }
if (xmldoc_parse_example(node, buffer)) {
ret = 1;
break;
}
/* parse <para> elements inside special tags. */ /* parse <para> elements inside special tags. */
for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) { for (node = ast_xml_node_get_children(node); node; node = ast_xml_node_get_next(node)) {
/* first <para> just print it without tabs at the begining. */ /* first <para> just print it without tabs at the begining. */
@@ -1585,7 +1648,7 @@ static int xmldoc_parse_variable(struct ast_xml_node *node, const char *tabs, st
/* Check inside this node for any explanation about its meaning. */ /* Check inside this node for any explanation about its meaning. */
if (tmptext) { if (tmptext) {
/* Cleanup text. */ /* Cleanup text. */
xmldoc_string_cleanup(tmptext, &cleanstr, 1); xmldoc_string_cleanup(tmptext, &cleanstr, 1, 0);
ast_xml_free_text(tmptext); ast_xml_free_text(tmptext);
if (cleanstr && ast_str_strlen(cleanstr) > 0) { if (cleanstr && ast_str_strlen(cleanstr) > 0) {
ast_str_append(buffer, 0, ":%s", ast_str_buffer(cleanstr)); ast_str_append(buffer, 0, ":%s", ast_str_buffer(cleanstr));
@@ -2147,18 +2210,24 @@ static struct ast_str *xmldoc_get_formatted(struct ast_xml_node *node, int raw_o
/* xmldoc_string_cleanup will allocate the ret object */ /* xmldoc_string_cleanup will allocate the ret object */
notcleanret = ast_xml_get_text(node); notcleanret = ast_xml_get_text(node);
tmpstr = notcleanret; tmpstr = notcleanret;
xmldoc_string_cleanup(ast_skip_blanks(notcleanret), &ret, 0); xmldoc_string_cleanup(ast_skip_blanks(notcleanret), &ret, 0, 0);
ast_xml_free_text(tmpstr); ast_xml_free_text(tmpstr);
} else { } else {
ret = ast_str_create(128); ret = ast_str_create(128);
for (tmp = ast_xml_node_get_children(node); tmp; tmp = ast_xml_node_get_next(tmp)) { for (tmp = ast_xml_node_get_children(node); tmp; tmp = ast_xml_node_get_next(tmp)) {
/* if found, parse a <para> element. */ /* if found, parse children elements. */
if (xmldoc_parse_common_elements(tmp, "", "\n", &ret)) { if (xmldoc_parse_common_elements(tmp, "", "\n", &ret)) {
continue; continue;
} }
/* if found, parse a <variablelist> element. */ if (xmldoc_parse_variablelist(tmp, "", &ret)) {
xmldoc_parse_variablelist(tmp, "", &ret); continue;
xmldoc_parse_enumlist(tmp, " ", &ret); }
if (xmldoc_parse_enumlist(tmp, " ", &ret)) {
continue;
}
if (xmldoc_parse_specialtags(tmp, "", "", &ret)) {
continue;
}
} }
/* remove last '\n' */ /* remove last '\n' */
/* XXX Don't modify ast_str internals manually */ /* XXX Don't modify ast_str internals manually */