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() == "*") {

Reply via email to