using std::vector;
using std::map;
+using lyx::support::changeExtension;
using lyx::support::isStrUnsignedInt;
using lyx::support::ltrim;
-using lyx::support::MakeAbsPath;
-using lyx::support::OnlyPath;
+using lyx::support::makeAbsPath;
+using lyx::support::onlyPath;
using lyx::support::rtrim;
-using lyx::support::IsFileReadable;
+using lyx::support::isFileReadable;
namespace fs = boost::filesystem;
}
-map<string, vector<ArgumentType> > known_commands;
+CommandMap known_commands;
+CommandMap known_environments;
+CommandMap known_math_environments;
void add_known_command(string const & command, string const & o1,
- bool o2)
+ bool o2)
{
// We have to handle the following cases:
// definition o1 o2 invocation result
namespace {
+/*!
+ * Read one command definition from the syntax file
+ */
+void read_command(Parser & p, string command, CommandMap & commands) {
+ if (p.next_token().asInput() == "*") {
+ p.get_token();
+ command += '*';
+ }
+ 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);
+ }
+ }
+ commands[command] = arguments;
+}
+
+
+/*!
+ * Read a class of environments from the syntax file
+ */
+void read_environment(Parser & p, string const & begin,
+ CommandMap & environments)
+{
+ string environment;
+ while (p.good()) {
+ Token const & t = p.get_token();
+ if (t.cat() == catLetter)
+ environment += t.asInput();
+ else if (!environment.empty()) {
+ p.putback();
+ read_command(p, environment, environments);
+ environment.erase();
+ }
+ if (t.cat() == catEscape && t.asInput() == "\\end") {
+ string const end = p.getArg('{', '}');
+ if (end == begin)
+ return;
+ }
+ }
+}
+
+
/*!
* 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
+ * are handled, it does not matter that the "syntax.default" file
* has almost all of them listed. For the same reason the reLyX-specific
* reLyXre environment is ignored.
*/
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);
- }
+ string const command = t.asInput();
+ if (command == "\\begin") {
+ string const name = p.getArg('{', '}');
+ if (name == "environments" || name == "reLyXre")
+ // We understand "reLyXre", but it is
+ // not as powerful as "environments".
+ read_environment(p, name,
+ known_environments);
+ else if (name == "mathenvironments")
+ read_environment(p, name,
+ known_math_environments);
+ } else {
+ read_command(p, command, known_commands);
}
- known_commands[command] = arguments;
}
}
}
int parse_help(string const &, string const &)
{
- cerr << "Usage: tex2lyx [ command line switches ] <infile.tex>\n"
- "Command line switches (case sensitive):\n"
- "\t-help summarize tex2lyx usage\n"
- "\t-f Force creation of .lyx files even if they exist already\n"
+ cerr << "Usage: tex2lyx [ command line switches ] <infile.tex> [<outfile.lyx>]\n"
+ "Command line switches (case sensitive):\n"
+ "\t-help summarize tex2lyx usage\n"
+ "\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\n"
- "\t-s syntaxfile read additional syntax file" << endl;
+ "\t-c textclass declare the textclass\n"
+ "\t-s syntaxfile read additional syntax file" << endl;
exit(0);
}
active_environments.push_back("document");
Context context(true, textclass);
parse_text(p, ss, FLAG_END, true, context);
+ if (Context::empty)
+ // Empty document body. LyX needs at least one paragraph.
+ context.check_layout(ss);
context.check_end_layout(ss);
ss << "\n\\end_body\n\\end_document\n";
active_environments.pop_back();
/// convert TeX from \p infilename to LyX and write it to \p os
bool tex2lyx(string const &infilename, std::ostream &os)
{
- BOOST_ASSERT(lyx::support::AbsolutePath(infilename));
+ BOOST_ASSERT(lyx::support::absolutePath(infilename));
ifstream is(infilename.c_str());
if (!is.good()) {
cerr << "Could not open input file \"" << infilename
return false;
}
string const oldParentFilePath = parentFilePath;
- parentFilePath = OnlyPath(infilename);
+ parentFilePath = onlyPath(infilename);
tex2lyx(is, os);
parentFilePath = oldParentFilePath;
return true;
bool tex2lyx(string const &infilename, string const &outfilename)
{
- if (!overwrite_files && IsFileReadable(outfilename)) {
- cerr << "Not overwriting existing file " << outfilename << "\n";
- return false;
+ if (isFileReadable(outfilename)) {
+ if (overwrite_files) {
+ cerr << "Overwriting existing file "
+ << outfilename << endl;
+ } else {
+ cerr << "Not overwriting existing file "
+ << outfilename << endl;
+ return false;
+ }
+ } else {
+ cerr << "Creating file " << outfilename << endl;
}
ofstream os(outfilename.c_str());
if (!os.good()) {
easyParse(argc, argv);
if (argc <= 1) {
- cerr << "Usage: tex2lyx [ command line switches ] <infile.tex>\n"
- "See tex2lyx -help." << endl;
+ cerr << "Usage: tex2lyx [ command line switches ] <infile.tex> [<outfile.lyx>]\n"
+ "See tex2lyx -help." << endl;
return 2;
}
lyx::support::init_package(argv[0], cl_system_support, cl_user_support,
lyx::support::top_build_dir_is_two_levels_up);
- string const system_syntaxfile = lyx::support::LibFileSearch("reLyX", "syntax.default");
+ // Now every known option is parsed. Look for input and output
+ // file name (the latter is optional).
+ string const infilename = makeAbsPath(argv[1]);
+ string outfilename;
+ if (argc > 2) {
+ outfilename = argv[2];
+ if (outfilename != "-")
+ outfilename = makeAbsPath(argv[2]);
+ } else
+ outfilename = changeExtension(infilename, ".lyx");
+
+ string const system_syntaxfile = lyx::support::libFileSearch("", "syntax.default");
if (system_syntaxfile.empty()) {
cerr << "Error: Could not find syntax file \"syntax.default\"." << endl;
exit(1);
if (!syntaxfile.empty())
read_syntaxfile(syntaxfile);
- string const infilename = MakeAbsPath(argv[1]);
- masterFilePath = OnlyPath(infilename);
+ masterFilePath = onlyPath(infilename);
parentFilePath = masterFilePath;
- if (tex2lyx(infilename, cout))
- return EXIT_SUCCESS;
- else
- return EXIT_FAILURE;
+ if (outfilename == "-") {
+ if (tex2lyx(infilename, cout))
+ return EXIT_SUCCESS;
+ else
+ return EXIT_FAILURE;
+ } else {
+ if (tex2lyx(infilename, outfilename))
+ return EXIT_SUCCESS;
+ else
+ return EXIT_FAILURE;
+ }
}
// }])