Fix arguments of @param, @return etc translations to Python.

For the parameter documentation to be really taken as such, in its entirety,
by Sphinx, it must be indented relative to the :param: tag. Do this by
appending an extra indent after every line of the output and work around the
unnecessary indent of the last line by removing the trailing whitespace.

This required updating the existing tests and removing the expected but not
present any more whitespace from them, but as trailing whitespace in the
documentation is at best insignificant (and at worst harmful) anyhow, this is
not a big price to pay for simpler translator code.
This commit is contained in:
Vadim Zeitlin 2014-07-13 20:27:52 +02:00
commit 8b83976f4c
7 changed files with 135 additions and 39 deletions

View file

@ -146,14 +146,14 @@ commentVerifier.check(doxygen_misc_constructs.cycle.__doc__,
Spaces at the start of line should be taken into account: Spaces at the start of line should be taken into account:
:type id: int :type id: int
:param id: used as prefix in log :param id: used as prefix in log
statements. The default value is empty string, which is OK if statements. The default value is empty string, which is OK if
there is only one app. instance. Example: there is only one app. instance. Example:
ctrl.setBP("func1"); ctrl.setBP("func1");
If we set the id to ``main_``, we get: If we set the id to ``main_``, we get:
main_ctrl.setBP("func1"); main_ctrl.setBP("func1");
:type fileName: string :type fileName: string

View file

@ -95,6 +95,7 @@ r"""
:math:`\sqrt{(x_2-x_1)^2+(y_2-y_1)^2}` :math:`\sqrt{(x_2-x_1)^2+(y_2-y_1)^2}`
.. math:: .. math::
\sqrt{(x_2-x_1)^2+(y_2-y_1)^2} \sqrt{(x_2-x_1)^2+(y_2-y_1)^2}
@ -116,7 +117,6 @@ r"""
This will only appear in hmtl This will only appear in hmtl
""") """)

View file

@ -228,14 +228,14 @@ r"""
:type byFlags: int :type byFlags: int
:param byFlags: bits marking required items: :param byFlags: bits marking required items:
| Size in bits| Items Required | | Size in bits| Items Required |
-------------------------------- --------------------------------
| 1 - 8 | 1 | | 1 - 8 | 1 |
| 9 - 16 | 2 | | 9 - 16 | 2 |
| 17 - 32 | 4 | | 17 - 32 | 4 |
Almost all combinations of above flags are supported by Almost all combinations of above flags are supported by
``htmlTable...`` functions. ``htmlTable...`` functions.
""") """)

View file

@ -24,6 +24,72 @@ std::map<std::string, std::string> PyDocConverter::sectionTitles;
using std::string; using std::string;
// Helper class increasing the provided indent string in its ctor and decreasing
// it in its dtor.
class IndentGuard
{
public:
// One indent level.
static const char* Level() { return " "; }
// Ctor takes the output to determine the current indent and to remove the
// extra indent added to it in the dtor and the variable containing the indent
// to use, which must be used after every new line by the code actually
// updating the output.
explicit IndentGuard(string& output, string& indent) :
m_output(output),
m_indent(indent)
{
const size_t lastNonSpace = m_output.find_last_not_of(' ');
if (lastNonSpace == string::npos) {
m_firstLineIndent = m_output.length();
} else if (m_output[lastNonSpace] == '\n') {
m_firstLineIndent = m_output.length() - (lastNonSpace + 1);
} else {
m_firstLineIndent = 0;
}
// Notice that the indent doesn't include the first line indent because it's
// implicit, i.e. it is present in the input and so is copied into the
// output anyhow.
m_indent = Level();
}
// Get the indent for the first line of the paragraph, which is smaller than
// the indent for the subsequent lines.
string getFirstLineIndent() const { return string(m_firstLineIndent, ' '); }
~IndentGuard()
{
m_indent.clear();
// Get rid of possible remaining extra indent, e.g. if there were any trailing
// new lines: we shouldn't add the extra indent level to whatever follows
// this paragraph.
static const size_t lenIndentLevel = strlen(Level());
if (m_output.length() > lenIndentLevel) {
const size_t start = m_output.length() - lenIndentLevel;
if (m_output.compare(start, string::npos, Level()) == 0)
m_output.erase(start);
}
}
private:
string& m_output;
string& m_indent;
unsigned m_firstLineIndent;
IndentGuard(const IndentGuard&);
IndentGuard& operator=(const IndentGuard&);
};
static void trimWhitespace(string& s)
{
const size_t lastNonSpace = s.find_last_not_of(' ');
if (lastNonSpace != string::npos)
s.erase(lastNonSpace + 1);
}
/* static */ /* static */
PyDocConverter::TagHandlersMap::mapped_type PyDocConverter::TagHandlersMap::mapped_type
PyDocConverter::make_handler(tagHandler handler) PyDocConverter::make_handler(tagHandler handler)
@ -311,13 +377,27 @@ void PyDocConverter::handleMath(DoxygenEntity &tag,
std::string &translatedComment, std::string &translatedComment,
const std::string& arg) const std::string& arg)
{ {
IndentGuard indent(translatedComment, m_indent);
// Only \f$ is translated to inline formulae, \f[ and \f{ are for the block ones. // Only \f$ is translated to inline formulae, \f[ and \f{ are for the block ones.
const bool inlineFormula = tag.typeOfEntity == "f$"; const bool inlineFormula = tag.typeOfEntity == "f$";
string formulaNL;
if (inlineFormula) { if (inlineFormula) {
translatedComment += ":math:`"; translatedComment += ":math:`";
} else { } else {
translatedComment += ".. math::\n\n "; trimWhitespace(translatedComment);
translatedComment += '\n';
const string formulaIndent = indent.getFirstLineIndent();
translatedComment += formulaIndent;
translatedComment += ".. math::\n";
formulaNL = '\n';
formulaNL += formulaIndent;
formulaNL += m_indent;
translatedComment += formulaNL;
} }
std::string formula; std::string formula;
@ -330,10 +410,9 @@ void PyDocConverter::handleMath(DoxygenEntity &tag,
if (start != std::string::npos) { if (start != std::string::npos) {
for (size_t n = start; n <= end; n++) { for (size_t n = start; n <= end; n++) {
if (formula[n] == '\n') { if (formula[n] == '\n') {
// New lines must be suppressed in inline maths and indented in the // New lines must be suppressed in inline maths and indented in the block ones.
// block ones.
if (!inlineFormula) if (!inlineFormula)
translatedComment += "\n "; translatedComment += formulaNL;
} else { } else {
// Just copy everything else. // Just copy everything else.
translatedComment += formula[n]; translatedComment += formula[n];
@ -344,7 +423,7 @@ void PyDocConverter::handleMath(DoxygenEntity &tag,
if (inlineFormula) { if (inlineFormula) {
translatedComment += "`"; translatedComment += "`";
} else { } else {
translatedComment += "\n\n"; translatedComment += '\n';
} }
} }
@ -427,16 +506,21 @@ void PyDocConverter::handleTagParam(DoxygenEntity& tag,
if (tag.entityList.size() < 2) if (tag.entityList.size() < 2)
return; return;
IndentGuard indent(translatedComment, m_indent);
DoxygenEntity paramNameEntity = *tag.entityList.begin(); DoxygenEntity paramNameEntity = *tag.entityList.begin();
tag.entityList.pop_front(); tag.entityList.pop_front();
const std::string& paramName = paramNameEntity.data; const std::string& paramName = paramNameEntity.data;
const std::string paramType = getParamType(paramName); const std::string paramType = getParamType(paramName);
if (!paramType.empty()) if (!paramType.empty()) {
translatedComment += ":type " + paramName + ": " + paramType + "\n"; translatedComment += ":type " + paramName + ": " + paramType + "\n";
translatedComment += indent.getFirstLineIndent();
}
translatedComment += ":param " + paramName + ":"; translatedComment += ":param " + paramName + ":";
handleParagraph(tag, translatedComment); handleParagraph(tag, translatedComment);
} }
@ -445,6 +529,8 @@ void PyDocConverter::handleTagReturn(DoxygenEntity &tag,
std::string &translatedComment, std::string &translatedComment,
const std::string &) const std::string &)
{ {
IndentGuard indent(translatedComment, m_indent);
translatedComment += ":return: "; translatedComment += ":return: ";
handleParagraph(tag, translatedComment); handleParagraph(tag, translatedComment);
} }
@ -454,6 +540,8 @@ void PyDocConverter::handleTagException(DoxygenEntity &tag,
std::string &translatedComment, std::string &translatedComment,
const std::string &) const std::string &)
{ {
IndentGuard indent(translatedComment, m_indent);
translatedComment += ":raises: "; translatedComment += ":raises: ";
handleParagraph(tag, translatedComment); handleParagraph(tag, translatedComment);
} }
@ -618,7 +706,11 @@ void PyDocConverter::handleNewLine(DoxygenEntity&,
std::string& translatedComment, std::string& translatedComment,
const std::string&) const std::string&)
{ {
trimWhitespace(translatedComment);
translatedComment += "\n"; translatedComment += "\n";
if (!m_indent.empty())
translatedComment += m_indent;
} }
String *PyDocConverter::makeDocumentation(Node *n) String *PyDocConverter::makeDocumentation(Node *n)

View file

@ -174,6 +174,10 @@ private:
// temporary thing, should be refactored somehow // temporary thing, should be refactored somehow
Node *currentNode; Node *currentNode;
// Extra indent for the current paragraph, must be output after each new line.
std::string m_indent;
// this contains the handler pointer and one string argument // this contains the handler pointer and one string argument
typedef std::map<std::string, std::pair<tagHandler, std::string> > TagHandlersMap; typedef std::map<std::string, std::pair<tagHandler, std::string> > TagHandlersMap;
static TagHandlersMap tagHandlers; static TagHandlersMap tagHandlers;