Am Freitag, 14. November 2003 21:11 schrieb Georg Baum:
> Yes. We can even steal the list of 'known' commands from
> lib/reLyX/syntax.default. Creating this list was the main thing that I
> did not like with this solution.

It turned out to be rather easy. I have used the syntax.default file from 
reLyX directly.


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/15 17:09:53
@@ -1,3 +1,10 @@
+2003-11-15  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 arguments correctly.
+
 2003-11-03  Georg Baum  <[EMAIL PROTECTED]>
 
 	* math.C:
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/15 17:09:57
@@ -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.size())
+		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/15 17:09:57
@@ -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/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/15 17:10:02
@@ -294,6 +310,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)
 {
@@ -1223,16 +1321,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 +1335,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