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


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@37064 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Georg Baum 2011-01-02 15:39:48 +00:00
parent a3a7c046be
commit 812c27d793
6 changed files with 116 additions and 49 deletions

View File

@ -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

View File

@ -293,6 +293,38 @@ char Parser::getChar()
}
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);

View File

@ -131,6 +131,8 @@ public:
/// 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;
/*!

View File

@ -968,6 +968,7 @@ void handle_tabular(Parser & p, ostream & os, bool is_long_tabular,
// 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

View File

@ -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 @@ Now the natbib things:
\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 @@ There is also some basic support for graphics, in the form
\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{longtable}{@{*}r||p{1in}@{*}}
KILLED & LINE!!!! \kill
@ -166,28 +167,28 @@ at the end& of the table\\
\endlastfoot
\env{longtable} columns are specified& in the \\
same way as in the \env{tabular}& environment.\\
"@{*}r||p{1in}@{*}"& in this case.\\
Each row ends with a& "\\" command.\\
The "\\" command has an& optional\\
%\code{@\{*\}r||p\{1in\}@\{*\}}& 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 @@ Some lines may take up a lot of space, like this: &
\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 @@ test
\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 @@ so we try to use ERT in this case.
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}}

View File

@ -455,7 +455,7 @@ void eat_whitespace(Parser &, ostream &, Context &, bool);
* 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 @@ void skip_spaces_braces(Parser & p)
// 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 @@ void parse_box(Parser & p, ostream & os, unsigned flags, bool outer,
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 @@ void parse_environment(Parser & p, ostream & os, bool outer,
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 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
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 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
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 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
}
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 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
}
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 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
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() == "*") {