Author: baum
Date: Sun Jan 2 16:39:48 2011
New Revision: 37064
URL: http://www.lyx.org/trac/changeset/37064
Log:
Improve tex2lyx roundtrip of test-insets.tex:
- Replace special verbatim commands by standard LaTeX, since it would be
extremely difficult to make tex2lyx understand them)
- Comment duplicated \bibliography{xampl}, since LaTeX cannot handle two
\bibliography calls
- Fix a regression with spaces after commands, introduced in r36943
- Parse \multicolumn with space/comments between two arguments correctly
- Parse optional arguments correctly if there are space or comments between
the command and the argument
- Remove duplicate "LyX" phrase handling (I overlooked that in r37052)
- Add new commands created with \let to the list of known commands. This is
needed to parse the arguments correctly
Modified:
lyx-devel/trunk/lib/syntax.default
lyx-devel/trunk/src/tex2lyx/Parser.cpp
lyx-devel/trunk/src/tex2lyx/Parser.h
lyx-devel/trunk/src/tex2lyx/table.cpp
lyx-devel/trunk/src/tex2lyx/test/test-insets.tex
lyx-devel/trunk/src/tex2lyx/text.cpp
Modified: lyx-devel/trunk/lib/syntax.default
==============================================================================
--- lyx-devel/trunk/lib/syntax.default Sun Jan 2 13:07:33 2011 (r37063)
+++ lyx-devel/trunk/lib/syntax.default Sun Jan 2 16:39:48 2011 (r37064)
@@ -629,7 +629,16 @@
\textcircled{translate}
\textcolor[]{,,}{translate}
%\textcolor{}{}
-\textnormal{translate}
+\textbf{translate} % hardcoded, but needed nevertheless for \let\xyz\textbf
+\textnormal{translate} % hardcoded, but needed nevertheless for
\let\xyz\textnormal
+\textmd{translate} % hardcoded, but needed nevertheless for \let\xyz\textmd
+\textit{translate} % hardcoded, but needed nevertheless for \let\xyz\textit
+\textrm{translate} % hardcoded, but needed nevertheless for \let\xyz\textrm
+\textsc{translate} % hardcoded, but needed nevertheless for \let\xyz\textsc
+\textsf{translate} % hardcoded, but needed nevertheless for \let\xyz\textsf
+\textsl{translate} % hardcoded, but needed nevertheless for \let\xyz\textsl
+\texttt{translate} % hardcoded, but needed nevertheless for \let\xyz\texttt
+\textup{translate} % hardcoded, but needed nevertheless for \let\xyz\textup
\textfraction
\thanks{translate}
\thicklines
Modified: lyx-devel/trunk/src/tex2lyx/Parser.cpp
==============================================================================
--- lyx-devel/trunk/src/tex2lyx/Parser.cpp Sun Jan 2 13:07:33 2011
(r37063)
+++ lyx-devel/trunk/src/tex2lyx/Parser.cpp Sun Jan 2 16:39:48 2011
(r37064)
@@ -293,6 +293,38 @@
}
+bool Parser::hasOpt()
+{
+ // An optional argument can occur in any of the following forms:
+ // - \foo[bar]
+ // - \foo [bar]
+ // - \foo
+ // [bar]
+ // - \foo %comment
+ // [bar]
+
+ // remember current position
+ unsigned int oldpos = pos_;
+ // skip spaces and comments
+ while (good()) {
+ get_token();
+ if (isParagraph()) {
+ putback();
+ break;
+ }
+ if (curr_token().cat() == catSpace ||
+ curr_token().cat() == catNewline ||
+ curr_token().cat() == catComment)
+ continue;
+ putback();
+ break;
+ }
+ bool const retval = (next_token().asInput() == "[");
+ pos_ = oldpos;
+ return retval;
+}
+
+
Parser::Arg Parser::getFullArg(char left, char right)
{
skip_spaces(true);
Modified: lyx-devel/trunk/src/tex2lyx/Parser.h
==============================================================================
--- lyx-devel/trunk/src/tex2lyx/Parser.h Sun Jan 2 13:07:33 2011
(r37063)
+++ lyx-devel/trunk/src/tex2lyx/Parser.h Sun Jan 2 16:39:48 2011
(r37064)
@@ -131,6 +131,8 @@
/// dump contents to screen
void dump() const;
+ /// Does an optional argument follow after the current token?
+ bool hasOpt();
///
typedef std::pair<bool, std::string> Arg;
/*!
Modified: lyx-devel/trunk/src/tex2lyx/table.cpp
==============================================================================
--- lyx-devel/trunk/src/tex2lyx/table.cpp Sun Jan 2 13:07:33 2011
(r37063)
+++ lyx-devel/trunk/src/tex2lyx/table.cpp Sun Jan 2 16:39:48 2011
(r37064)
@@ -968,6 +968,7 @@
// special cell properties alignment
vector<ColInfo> t;
handle_colalign(p, t, ColInfo());
+ p.skip_spaces(true);
ColInfo & ci = t.front();
// The logic of LyX for multicolumn vertical
Modified: lyx-devel/trunk/src/tex2lyx/test/test-insets.tex
==============================================================================
--- lyx-devel/trunk/src/tex2lyx/test/test-insets.tex Sun Jan 2 13:07:33
2011 (r37063)
+++ lyx-devel/trunk/src/tex2lyx/test/test-insets.tex Sun Jan 2 16:39:48
2011 (r37064)
@@ -32,7 +32,6 @@
\newcommand{\lyxarrow}{\leavevmode\,$\triangleright$\,\allowbreak}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% User specified LaTeX commands.
-\usepackage{doc}
\usepackage{subscript} % user specified as long as tex2lyx
% produces a format less than 408
@@ -94,7 +93,8 @@
\textbackslash{}nocite: \nocite{article-crossref}
\bibliographystyle{unsrt}
-\bibliography{xampl}
+% Remove duplicate call of \bibliography since LaTeX throws an error.
+% \bibliography{xampl}
With \textbackslash{}nocite\{{*}\}:
\bibliographystyle{unsrt}
@@ -129,12 +129,13 @@
\section{Tables\index{Tables}}
The following example is stolen from the longtable documentation.
+Since tex2lyx does not understand the special verbatim code that
+was used in the original some lines have been rewritten using
+\textbackslash textbackslash etc.
\let\package\textsf
\let\env\textsf
+\let\code\texttt
\providecommand\finalclearpage{\clearpage}
-\DeleteShortVerb{\|}
-\MakeShortVerb{\"}
-\def\v{\char`}
\begin{longtabl...@{*}r||p{1...@{*}}
KILLED & LINE!!!! \kill
@@ -166,28 +167,28 @@
\endlastfoot
\env{longtable} columns are specified& in the \\
same way as in the \env{tabular}& environment.\\
-"@{*}r||p{1...@{*}"& in this case.\\
-Each row ends with a& "\\" command.\\
-The "\\" command has an& optional\\
+%\co...@\{*\}r||p\{1i...@\{*\}}& in this case.\\
+Each row ends with a& \code{\textbackslash\textbackslash} command.\\
+The \code{\textbackslash\textbackslash} command has an& optional\\
argument, just as in& the\\
\env{tabular}&environment.\\[10pt]
-See the effect of "\\[10pt]"&?\\
+See the effect of \code{\textbackslash\textbackslash[10pt]}&?\\
Lots of lines& like this.\\
Lots of lines& like this.\\
Lots of lines& like this.\\
Lots of lines& like this.\\
-Also "\hline" may be used,& as in \env{tabular}.\\
+Also \code{\textbackslash hline} may be used,& as in \env{tabular}.\\
\hline
-That was a "\hline"&.\\
+That was a \code{\textbackslash hline}&.\\
\hline\hline
-That was "\hline\hline"&.\\
+That was \code{\textbackslash hline\textbackslash hline}&.\\
\multicolumn{2}{||c||}%
-{This is a \ttfamily\v\\multicolumn\v{2\v}\v{||c||\v}}\\
-If a page break occurs at a "\hline" then& a line is drawn\\
+{This is a \code{\textbackslash multicolumn\{2\}\{||c||\}}}\\
+If a page break occurs at a \code{\textbackslash hline} then& a line is
drawn\\
at the bottom of one page and at the& top of the next.\\
\hline
-The "[t] [b] [c]" argument of \env{tabular}& can not be used.\\
-The optional argument may be one of& "[l] [r] [c]"\\
+The \code{[t] [b] [c]} argument of \env{tabular}& can not be used.\\
+The optional argument may be one of& \code{[l] [r] [c]}\\
to specify whether the table should be& adjusted\\
to the left, right& or centrally.\\
\hline\hline
@@ -215,7 +216,7 @@
\raggedleft This last column is a ``p'' column so this
``row'' of the table can take up several lines. Note however that
\TeX\ will never break a page within such a row. Page breaks only
- occur between rows of the table or at "\hline" commands.
+ occur between rows of the table or at \code{\textbackslash hline} commands.
\tabularnewline
Lots of lines& like this.\\
Lots of lines& like this.\\
@@ -268,9 +269,13 @@
\subsection{Line breaks}
They can also or be broken by a newline\\
-or a newline command \newline
+or by a starred newline \\*
+or by a newline with space, comment and argument \\ %hu
+[3cm]
+or by a newline command \newline
or by a line break \linebreak
-or by a defined line break \linebreak[4]
+or by a defined line break \linebreak % again with a comment
+ [4]
There are even newlines with weird arguments, but these are not
handled by LyX\\*[1cm]
@@ -280,7 +285,8 @@
They can also or be broken by a newpage \newpage
or by a page break \pagebreak
-or by a defined page break \pagebreak[4]
+or by a defined page break \pagebreak % again with a comment
+ [4]
\section{Special characters\index{Special characters}}
Modified: lyx-devel/trunk/src/tex2lyx/text.cpp
==============================================================================
--- lyx-devel/trunk/src/tex2lyx/text.cpp Sun Jan 2 13:07:33 2011
(r37063)
+++ lyx-devel/trunk/src/tex2lyx/text.cpp Sun Jan 2 16:39:48 2011
(r37064)
@@ -455,7 +455,7 @@
* This should be called after a command has been parsed that is not put into
* ERT, and where LyX adds "{}" if needed.
*/
-void skip_spaces_braces(Parser & p)
+void skip_spaces_braces(Parser & p, bool keepws = false)
{
/* The following four examples produce the same typeset output and
should be handled by this function:
@@ -471,7 +471,7 @@
// results in different output in some cases.
bool const skipped_spaces = p.skip_spaces(true);
bool const skipped_braces = skip_braces(p);
- if (skipped_spaces && !skipped_braces)
+ if (keepws && skipped_spaces && !skipped_braces)
// put back the space (it is better handled by check_space)
p.unskip_spaces(true);
}
@@ -643,17 +643,17 @@
string height_unit = "in";
string height_special = "totalheight";
string latex_height;
- if (p.next_token().asInput() == "[") {
+ if (p.hasOpt()) {
position = p.getArg('[', ']');
if (position != "t" && position != "c" && position != "b") {
position = "c";
cerr << "invalid position for minipage/parbox" << endl;
}
- if (p.next_token().asInput() == "[") {
+ if (p.hasOpt()) {
latex_height = p.getArg('[', ']');
translate_box_len(latex_height, height_value,
height_unit, height_special);
- if (p.next_token().asInput() == "[") {
+ if (p.hasOpt()) {
inner_pos = p.getArg('[', ']');
if (inner_pos != "c" && inner_pos != "t" &&
inner_pos != "b" && inner_pos != "s") {
@@ -794,9 +794,8 @@
eat_whitespace(p, os, parent_context, false);
parent_context.check_layout(os);
begin_inset(os, "Float " + unstarred_name + "\n");
- if (p.next_token().asInput() == "[") {
+ if (p.hasOpt())
os << "placement " << p.getArg('[', ']') << '\n';
- }
os << "wide " << convert<string>(is_starred)
<< "\nsideways false"
<< "\nstatus open\n\n";
@@ -2464,19 +2463,6 @@
p.setEncoding(enc);
}
- else if (t.cs() == "LyX" || t.cs() == "TeX"
- || t.cs() == "LaTeX") {
- context.check_layout(os);
- os << t.cs();
- skip_spaces_braces(p);
- }
-
- else if (t.cs() == "LaTeXe") {
- context.check_layout(os);
- os << "LaTeX2e";
- skip_spaces_braces(p);
- }
-
else if (t.cs() == "ldots") {
context.check_layout(os);
os << "\\SpecialChar \\ldots{}\n";
@@ -2603,11 +2589,13 @@
else if (t.cs() == "\\") {
context.check_layout(os);
- string const next = p.next_token().asInput();
- if (next == "[")
+ if (p.hasOpt())
handle_ert(os, "\\\\" + p.getOpt(), context);
- else if (next == "*") {
+ else if (p.next_token().asInput() == "*") {
p.get_token();
+ // getOpt() eats the following space if there
+ // is no optional argument, but that is OK
+ // here since it has no effect in the output.
handle_ert(os, "\\\\*" + p.getOpt(), context);
}
else {
@@ -2617,8 +2605,7 @@
}
else if (t.cs() == "newline" ||
- (t.cs() == "linebreak" &&
- p.next_token().asInput() != "[")) {
+ (t.cs() == "linebreak" && !p.hasOpt())) {
context.check_layout(os);
begin_inset(os, "Newline ");
os << t.cs();
@@ -2804,8 +2791,7 @@
}
else if (t.cs() == "newpage" ||
- (t.cs() == "pagebreak" &&
- p.next_token().asInput() != "[") ||
+ (t.cs() == "pagebreak" && !p.hasOpt()) ||
t.cs() == "clearpage" ||
t.cs() == "cleardoublepage") {
context.check_layout(os);
@@ -2843,7 +2829,38 @@
end_inset(os);
}
}
-
+
+ else if (t.cs() == "let" && p.next_token().asInput() != "*") {
+ // let could be handled by parse_command(),
+ // but we need to call add_known_command() here.
+ string ert = t.asInput();
+ string name;
+ p.skip_spaces();
+ if (p.next_token().cat() == catBegin) {
+ name = p.verbatim_item();
+ ert += '{' + name + '}';
+ } else {
+ name = p.verbatim_item();
+ ert += name;
+ }
+ string command;
+ p.skip_spaces();
+ if (p.next_token().cat() == catBegin) {
+ command = p.verbatim_item();
+ ert += '{' + command + '}';
+ } else {
+ command = p.verbatim_item();
+ ert += command;
+ }
+ // If command is known, make name known too, to parse
+ // its arguments correctly. For this reason we also
+ // have commands in syntax.default that are hardcoded.
+ CommandMap::iterator it = known_commands.find(command);
+ if (it != known_commands.end())
+ known_commands[t.asInput()] = it->second;
+ handle_ert(os, ert, context);
+ }
+
else if (t.cs() == "hspace" || t.cs() == "vspace") {
bool starred = false;
if (p.next_token().asInput() == "*") {