The old fix was incomplete (\verb~\~ was translated to \verb~~ in roundtrip).
The real cause for this bug (and also the mistranslation of \href{...}{\}})
was the misbehaviour of Token::character() (see comment in Parser.h): This
method even returns a character if the category is catEscape, and this is not
wanted in most (all?) cases.
}
-Parser::Arg Parser::getFullArg(char left, char right)
+Parser::Arg Parser::getFullArg(char left, char right, bool allow_escaping)
{
skip_spaces(true);
return make_pair(false, string());
string result;
- char c = getChar();
+ Token t = get_token();
- if (c != left) {
+ if (t.cat() == catComment || t.cat() == catEscape ||
+ t.character() != left) {
putback();
return make_pair(false, string());
} else {
- // a single '\' is only allowed within \verb, no matter what the delimiter is,
- // for example "\verb+\+" (reported as bug #4468)
- // To support this, we allow single '\' if it is the only character
- // within equal delimiters
- if (next_token().cat() == catEscape)
- if (next_token().character() == right && right == left)
- result += '\\';
- while ((c = getChar()) != right && good()) {
+ for (t = get_token(); good(); t = get_token()) {
// Ignore comments
- if (curr_token().cat() == catComment) {
- if (!curr_token().cs().empty())
- cerr << "Ignoring comment: " << curr_token().asInput();
+ if (t.cat() == catComment) {
+ if (!t.cs().empty())
+ cerr << "Ignoring comment: " << t.asInput();
+ continue;
}
- else
- result += curr_token().asInput();
+ if (allow_escaping) {
+ if (t.cat() != catEscape && t.character() == right)
+ break;
+ } else {
+ if (t.character() == right) {
+ if (t.cat() == catEscape)
+ result += '\\';
+ break;
+ }
+ }
+ result += t.asInput();
}
}
return make_pair(true, result);
}
-string Parser::getArg(char left, char right)
+string Parser::getArg(char left, char right, bool allow_escaping)
{
- return getFullArg(left, right).second;
+ return getFullArg(left, right, allow_escaping).second;
}
* ../mathed/MathParser.cpp (which is the anchestor of this
* class) uses a separate char member for this method. I
* believe that the intended usage is to not cover tokens with
- * catEscape, e.g. \code
- * return (cs_.empty() || cat_ == catEscape) ? 0 : cs_[0];
+ * catEscape or catComment, e.g. \code
+ * return (cs_.empty() || cat_ == catEscape || cat_ == catComment) ? 0 : cs_[0];
* \endcode
* All usages of this method should be checked. gb 2011-01-05
*/
typedef std::pair<bool, std::string> Arg;
/*!
* Get an argument enclosed by \p left and \p right.
+ * If \p allow_escaping is true, a right delimiter escaped by a
+ * backslash does not count as delimiter, but is included in the
+ * argument.
* \returns wether an argument was found in \p Arg.first and the
* argument in \p Arg.second. \see getArg().
*/
- Arg getFullArg(char left, char right);
+ Arg getFullArg(char left, char right, bool allow_escaping = true);
/*!
* Get an argument enclosed by \p left and \p right.
+ * If \p allow_escaping is true, a right delimiter escaped by a
+ * backslash does not count as delimiter, but is included in the
+ * argument.
* \returns the argument (without \p left and \p right) or the empty
* string if the next non-space token is not \p left. Use
* getFullArg() if you need to know wether there was an empty
* argument or no argument at all.
*/
- std::string getArg(char left, char right);
+ std::string getArg(char left, char right, bool allow_escaping = true);
/*!
* Like getOpt(), but distinguishes between a missing argument ""
* and an empty argument "[]".
\end_inset
+\end_layout
+
+\begin_layout Standard
+
+parser test (escaped):
+\begin_inset CommandInset href
+LatexCommand href
+name "a brace } and another one { and something"
+target "http://www.test.test"
+
+\end_inset
+
+
\end_layout
\begin_layout Section
parser test (stupid, but valid):\href{http://www.test.test}{\}}
+parser test (escaped):\href{http://www.test.test}{a brace \} and another one \{ and something}
+
\section{Lists\index{Lists}}
\backslash
-verb~~
+verb~
+\backslash
+~
\end_layout
\end_inset
\end_inset
+
+\begin_inset ERT
+status collapsed
+
+\begin_layout Standard
+
+
+\backslash
+verb+something
+\backslash
++
+\end_layout
+
+\end_inset
+ bug 4468
\end_layout
\begin_layout Standard
\end{verbatim}
\verb~\~
\verb+\item[ABC] first item+
+\verb+something\+ bug 4468
and bibliography:
\begin{thebibliography}{9}
else if (t.cs() == "href") {
context.check_layout(os);
- string target = p.getArg('{', '}');
- string name = p.getArg('{', '}');
+ string target = convert_command_inset_arg(p.verbatim_item());
+ string name = convert_command_inset_arg(p.verbatim_item());
string type;
size_t i = target.find(':');
if (i != string::npos) {
else if (t.cs() == "verb") {
context.check_layout(os);
char const delimiter = p.next_token().character();
- string const arg = p.getArg(delimiter, delimiter);
+ // \verb is special: The usual escaping rules do not
+ // apply, e.g. "\verb+\+" is valid and denotes a single
+ // backslash (bug #4468). Therefore we do not allow
+ // escaping in getArg().
+ string const arg = p.getArg(delimiter, delimiter, false);
ostringstream oss;
oss << "\\verb" << delimiter << arg << delimiter;
handle_ert(os, oss.str(), context);