Am Dienstag, 18. November 2003 09:37 schrieb Andre Poenitz:
> On Mon, Nov 17, 2003 at 08:58:36PM +0100, Georg Baum wrote:
> > Am Montag, 17. November 2003 09:52 schrieb Andre Poenitz:
> > > Looks good. Is this ready for 'commit'?
> >
> > Yes. Maybe with the size() -> !empty() change suggested by Angus. BTW,
> > this construct is used at a few other places in tex2lyx, some from me,
> > some from others.
>
> Feel free to correct that.

See attached.

Georg
Index: src/tex2lyx/ChangeLog
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/ChangeLog,v
retrieving revision 1.41
diff -u -p -r1.41 ChangeLog
--- src/tex2lyx/ChangeLog	2003/11/05 10:14:12	1.41
+++ src/tex2lyx/ChangeLog	2003/11/18 21:11:29
@@ -1,3 +1,16 @@
+2003-11-18  Georg Baum  <[EMAIL PROTECTED]>
+
+	* tex2lyx.C:
+	* tex2lyx.h:
+	* text.C: Read a list of commands and their arguments from a reLyX
+	compatible syntax file in order to parse optional argumnts correctly.
+	* preamble.C:
+	* table.C:
+	* text.C:
+	* tex2lyx.C:
+	* texparser.C
+	* math.C: change size() to !empty() where it was used as bool
+
 2003-11-03  Georg Baum  <[EMAIL PROTECTED]>
 
 	* math.C:
Index: src/tex2lyx/math.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/math.C,v
retrieving revision 1.12
diff -u -p -r1.12 math.C
--- src/tex2lyx/math.C	2003/11/05 10:14:12	1.12
+++ src/tex2lyx/math.C	2003/11/18 21:11:29
@@ -121,7 +121,7 @@ void parse_math(Parser & p, ostream & os
 		}
 
 		else if (t.cat() == catComment) {
-			if (t.cs().size())
+			if (!t.cs().empty())
 				cerr << "Ignoring comment: " << t.asInput();
 			else
 				// "%\n" combination
Index: src/tex2lyx/preamble.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/preamble.C,v
retrieving revision 1.17
diff -u -p -r1.17 preamble.C
--- src/tex2lyx/preamble.C	2003/11/05 10:14:12	1.17
+++ src/tex2lyx/preamble.C	2003/11/18 21:11:31
@@ -131,7 +131,7 @@ void handle_package(string const & name,
 		h_language = name;
 		h_quotes_language = name;
 	} else {
-		if (options.size())
+		if (!options.empty())
 			h_preamble << "\\usepackage[" << options << "]{" << name << "}\n";
 		else
 			h_preamble << "\\usepackage{" << name << "}\n";
@@ -146,7 +146,7 @@ void end_preamble(ostream & os, LyXTextC
 	   << "\\lyxformat 225\n"
 	   << "\\textclass " << h_textclass << "\n"
 	   << "\\begin_preamble\n" << h_preamble.str() << "\n\\end_preamble\n";
-	if (h_options.size())
+	if (!h_options.empty())
 	   os << "\\options " << h_options << "\n";
 	os << "\\language " << h_language << "\n"
 	   << "\\inputencoding " << h_inputencoding << "\n"
@@ -319,7 +319,7 @@ LyXTextClass const parse_preamble(Parser
 			trim(name);
 			int nargs = 0;
 			string opts = p.getOpt();
-			if (opts.size()) {
+			if (!opts.empty()) {
 				istringstream is(string(opts, 1));
 				//cerr << "opt: " << is.str() << "\n";
 				is >> nargs;
@@ -361,13 +361,13 @@ LyXTextClass const parse_preamble(Parser
 			h_preamble << "\\begin{" << name << "}";
 		}
 
-		else if (t.cs().size())
+		else if (!t.cs().empty())
 			h_preamble << '\\' << t.cs();
 	}
 	p.skip_spaces();
 
 	// Force textclass if the user wanted it
-	if (forceclass.size()) {
+	if (!forceclass.empty()) {
 		h_textclass = forceclass;
 	}
 	string layoutfilename = LibFileSearch("layouts", h_textclass, "layout");
@@ -377,7 +377,7 @@ LyXTextClass const parse_preamble(Parser
 	}
 	LyXTextClass textclass;
 	textclass.Read(layoutfilename);
-	if (! h_papersides.size()) {
+	if (h_papersides.empty()) {
 		ostringstream ss;
 		ss << textclass.sides();
 		h_papersides = ss.str();
Index: src/tex2lyx/table.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/table.C,v
retrieving revision 1.23
diff -u -p -r1.23 table.C
--- src/tex2lyx/table.C	2003/11/05 10:14:12	1.23
+++ src/tex2lyx/table.C	2003/11/18 21:11:32
@@ -299,7 +299,7 @@ void handle_tabular(Parser & p, ostream 
 		    Context & context)
 {
 	string posopts = p.getOpt();
-	if (posopts.size())
+	if (!posopts.empty())
 		cerr << "vertical tabular positioning '" << posopts << "' ignored\n";
 
 	vector<ColInfo>            colinfo;
@@ -484,9 +484,9 @@ void handle_tabular(Parser & p, ostream 
 			os << " leftline=\"true\"";
 		if (colinfo[col].rightline)
 			os << " rightline=\"true\"";
-		if (colinfo[col].width.size())
+		if (!colinfo[col].width.empty())
 			os << " width=\"" << colinfo[col].width << "\"";
-		if (colinfo[col].special.size())
+		if (!colinfo[col].special.empty())
 			os << " special=\"" << colinfo[col].special << "\"";
 		os << ">\n";
 	}
Index: src/tex2lyx/tex2lyx.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/tex2lyx.C,v
retrieving revision 1.53
diff -u -p -r1.53 tex2lyx.C
--- src/tex2lyx/tex2lyx.C	2003/11/05 10:14:13	1.53
+++ src/tex2lyx/tex2lyx.C	2003/11/18 21:11:33
@@ -43,6 +43,7 @@ using std::ostringstream;
 using std::stringstream;
 using std::string;
 using std::vector;
+using std::map;
 
 using lyx::support::system_lyxdir;
 using lyx::support::user_lyxdir;
@@ -114,7 +115,63 @@ string active_environment()
 }
 
 
+map<string, vector<ArgumentType> > known_commands;
+
+
+namespace {
+
+
+/*!
+ * Read a list of TeX commands from a reLyX compatible syntax file.
+ * Since this list is used after all commands that have a LyX counterpart
+ * are handled, it does not matter that the "syntax.default" file from reLyX
+ * has almost all of them listed. For the same reason the reLyX-specific
+ * reLyXre environment is ignored.
+ */
+void read_syntaxfile(string const & file_name)
+{
+	if (!IsFileReadable(file_name)) {
+		cerr << "Could not open syntax file \"" << file_name
+		     << "\" for reading." << endl;
+		exit(2);
+	}
+	ifstream is(file_name.c_str());
+	// We can use our TeX parser, since the syntax of the layout file is
+	// modeled after TeX.
+	// Unknown tokens are just silently ignored, this helps us to skip some
+	// reLyX specific things.
+	Parser p(is);
+	while (p.good()) {
+		Token const & t = p.get_token();
+		if (t.cat() == catEscape) {
+			string command = t.asInput();
+			if (p.next_token().asInput() == "*") {
+				p.get_token();
+				command += '*';
+			}
+			p.skip_spaces();
+			vector<ArgumentType> arguments;
+			while (p.next_token().cat() == catBegin ||
+			       p.next_token().asInput() == "[") {
+				if (p.next_token().cat() == catBegin) {
+					string const arg = p.getArg('{', '}');
+					if (arg == "translate")
+						arguments.push_back(required);
+					else
+						arguments.push_back(verbatim);
+				} else {
+					p.getArg('[', ']');
+					arguments.push_back(optional);
+				}
+			}
+			known_commands[command] = arguments;
+		}
+	}
+}
+
+
 string documentclass;
+string syntaxfile;
 bool overwrite_files = false;
 
 
@@ -130,7 +187,8 @@ int parse_help(string const &, string co
 	        "\t-f                 Force creation of .lyx files even if they exist already\n"
 		"\t-userdir dir       try to set user directory to dir\n"
 		"\t-sysdir dir        try to set system directory to dir\n"
-	        "\t-c textclass       declare the textclass" << endl;
+	        "\t-c textclass       declare the textclass\n"
+	        "\t-s syntaxfile      read additional syntax file" << endl;
 	exit(0);
 }
 
@@ -146,6 +204,17 @@ int parse_class(string const & arg, stri
 }
 
 
+int parse_syntaxfile(string const & arg, string const &)
+{
+	if (arg.empty()) {
+		cerr << "Missing syntaxfile string after -s switch" << endl;
+		exit(1);
+	}
+	syntaxfile = arg;
+	return 1;
+}
+
+
 int parse_sysdir(string const & arg, string const &)
 {
 	if (arg.empty()) {
@@ -177,10 +246,11 @@ int parse_force(string const &, string c
 
 void easyParse(int & argc, char * argv[])
 {
-	std::map<string, cmd_helper> cmdmap;
+	map<string, cmd_helper> cmdmap;
 
 	cmdmap["-c"] = parse_class;
 	cmdmap["-f"] = parse_force;
+	cmdmap["-s"] = parse_syntaxfile;
 	cmdmap["-help"] = parse_help;
 	cmdmap["--help"] = parse_help;
 	cmdmap["-sysdir"] = parse_sysdir;
@@ -208,6 +278,8 @@ void easyParse(int & argc, char * argv[]
 	}
 }
 
+} // anonymous namespace
+
 
 void tex2lyx(std::istream &is, std::ostream &os)
 {
@@ -266,6 +338,15 @@ int main(int argc, char * argv[])
 
 	lyx::support::os::init(&argc, &argv);
 	lyx::support::setLyxPaths();
+
+	string const system_syntaxfile = lyx::support::LibFileSearch("reLyX", "syntax.default");
+	if (system_syntaxfile.empty()) {
+		cerr << "Error: Could not find syntax file \"syntax.default\"." << endl;
+		exit(1);
+	}
+	read_syntaxfile(system_syntaxfile);
+	if (!syntaxfile.empty())
+		read_syntaxfile(syntaxfile);
 
 	if (!IsFileReadable(argv[1])) {
 		cerr << "Could not open input file \"" << argv[1]
Index: src/tex2lyx/tex2lyx.h
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/tex2lyx.h,v
retrieving revision 1.12
diff -u -p -r1.12 tex2lyx.h
--- src/tex2lyx/tex2lyx.h	2003/11/05 10:14:13	1.12
+++ src/tex2lyx/tex2lyx.h	2003/11/18 21:11:33
@@ -19,6 +19,7 @@
 #include <iosfwd>
 #include <string>
 #include <vector>
+#include <map>
 
 class Context;
 
@@ -59,6 +60,15 @@ char const ** is_known(std::string const
 // Access to environment stack
 extern std::vector<std::string> active_environments;
 std::string active_environment();
+
+enum ArgumentType {
+	required,
+	verbatim,
+	optional
+};
+
+/// Known TeX commands with arguments that get parsed into ERT.
+extern std::map<std::string, std::vector<ArgumentType> > known_commands;
 
 /*! Reads tex input from \a is and writes lyx output to \a os.
  *  Uses some common settings for the preamble, so this should only
Index: src/tex2lyx/texparser.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/texparser.C,v
retrieving revision 1.23
diff -u -p -r1.23 texparser.C
--- src/tex2lyx/texparser.C	2003/11/05 10:14:13	1.23
+++ src/tex2lyx/texparser.C	2003/11/18 21:11:34
@@ -250,7 +250,7 @@ string Parser::getArg(char left, char ri
 		while ((c = getChar()) != right && good()) {
 			// Ignore comments
 			if (curr_token().cat() == catComment) {
-				if (curr_token().cs().size())
+				if (!curr_token().cs().empty())
 					cerr << "Ignoring comment: " << curr_token().asInput();
 			}
 			else if (curr_token().cat() == catSpace || curr_token().cat() == catNewline)
Index: src/tex2lyx/text.C
===================================================================
RCS file: /cvs/lyx/lyx-devel/src/tex2lyx/text.C,v
retrieving revision 1.27
diff -u -p -r1.27 text.C
--- src/tex2lyx/text.C	2003/11/05 10:14:13	1.27
+++ src/tex2lyx/text.C	2003/11/18 21:11:37
@@ -294,6 +294,43 @@ void check_space(Parser const & p, ostre
 	os << ' ';
 }
 
+
+/*!
+ * Check wether \param command is a known command. If yes,
+ * handle the command with all arguments.
+ * \return true if the command was parsed, false otherwise.
+ */
+bool parse_command(string const & command, Parser & p, ostream & os,
+                   bool outer, Context & context)
+{
+	if (known_commands.find(command) != known_commands.end()) {
+		vector<ArgumentType> const & template_arguments = known_commands[command];
+		string ert = command;
+		size_t no_arguments = template_arguments.size();
+		for (size_t i = 0; i < no_arguments; ++i) {
+			switch (template_arguments[i]) {
+			case required:
+				// This argument contains regular LaTeX
+				handle_ert(os, ert + '{', context);
+				parse_text(p, os, FLAG_ITEM, outer, context);
+				ert = "}";
+				break;
+			case verbatim:
+				// This argument may contain special characters
+				ert += '{' + p.verbatim_item() + '}';
+				break;
+			case optional:
+				ert += p.getOpt();
+				break;
+			}
+		}
+		handle_ert(os, ert, context);
+		return true;
+	}
+	return false;
+}
+
+
 void parse_environment(Parser & p, ostream & os, bool outer,
 		       Context & parent_context)
 {
@@ -377,11 +414,11 @@ void parse_environment(Parser & p, ostre
 			// lyx can't handle length variables
 			ostringstream ss;
 			ss << "\\begin{minipage}";
-			if (latex_position.size())
+			if (!latex_position.empty())
 				ss << '[' << latex_position << ']';
-			if (latex_height.size())
+			if (!latex_height.empty())
 				ss << '[' << latex_height << ']';
-			if (latex_inner_pos.size())
+			if (!latex_inner_pos.empty())
 				ss << '[' << latex_inner_pos << ']';
 			ss << "{" << width << "}";
 			handle_ert(os, ss.str(), parent_context);
@@ -628,7 +665,7 @@ void parse_text(Parser & p, ostream & os
 
 		else if (t.cat() == catComment) {
 			context.check_layout(os);
-			if (t.cs().size()) {
+			if (!t.cs().empty()) {
 				handle_comment(os, '%' + t.cs(), context);
 				if (p.next_token().cat() == catNewline) {
 					// A newline after a comment line starts a new paragraph
@@ -696,7 +733,7 @@ void parse_text(Parser & p, ostream & os
 					handle_ert(os, "[", context);
 					os << s;
 					handle_ert(os, "]", context);
-				} else if (s.size()) {
+				} else if (!s.empty()) {
 					// The space is needed to separate the item from the rest of the sentence.
 					os << s << ' ';
 					p.skip_spaces();
@@ -781,7 +818,7 @@ void parse_text(Parser & p, ostream & os
 				if (opt.find('t') != string::npos) ss << "Top";
 				if (opt.find('b') != string::npos) ss << "Bottom";
 				if (opt.find('B') != string::npos) ss << "Baseline";
-				if (ss.str().size())
+				if (!ss.str().empty())
 					os << "\trotateOrigin " << ss.str() << '\n';
 				else
 					cerr << "Warning: Ignoring unknown includegraphics origin argument '" << opt << "'\n";
@@ -838,7 +875,7 @@ void parse_text(Parser & p, ostream & os
 			if (opts.find("command") != opts.end())
 				special << "command=" << opts["command"] << ',';
 			string s_special = special.str();
-			if (s_special.size()) {
+			if (!s_special.empty()) {
 				// We had special arguments. Remove the trailing ','.
 				os << "\tspecial " << s_special.substr(0, s_special.size() - 1) << '\n';
 			}
@@ -1187,7 +1224,7 @@ void parse_text(Parser & p, ostream & os
 			begin_inset(os, "LatexCommand ");
 			os << "\\bibtex";
 			// Do we have a bibliographystyle set?
-			if (bibliographystyle.size()) {
+			if (!bibliographystyle.empty()) {
 				os << '[' << bibliographystyle << ']';
 			}
 			os << '{' << p.verbatim_item() << "}\n";
@@ -1223,16 +1260,6 @@ void parse_text(Parser & p, ostream & os
 			// next paragraph.
 		}
 
-		else if (t.cs() == "psfrag") {
-			// psfrag{ps-text}[ps-pos][tex-pos]{tex-text}
-			// TODO: Generalize this!
-			string arguments = p.getArg('{', '}');
-			arguments += '}';
-			arguments += p.getOpt();
-			arguments += p.getOpt();
-			handle_ert(os, "\\psfrag{" + arguments, context);
-		}
-
 		else {
 			//cerr << "#: " << t << " mode: " << mode << endl;
 			// heuristic: read up to next non-nested space
@@ -1247,14 +1274,14 @@ void parse_text(Parser & p, ostream & os
 			cerr << "found ERT: " << s << endl;
 			handle_ert(os, s + ' ', context);
 			*/
-			context.check_layout(os);
 			string name = t.asInput();
 			if (p.next_token().asInput() == "*") {
 				// Starred commands like \vspace*{}
 				p.get_token();				// Eat '*'
 				name += '*';
 			}
-			handle_ert(os, name, context);
+			if (! parse_command(t.asInput(), p, os, outer, context))
+				handle_ert(os, name, context);
 		}
 
 		if (flags & FLAG_LEAVE) {

Reply via email to