mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-10 20:04:46 +00:00
latest patch from Georg: support a syntax table for unsupported commands
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8104 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
25b208aa25
commit
f5d5eebe3c
@ -1,3 +1,16 @@
|
||||
2003-11-18 Georg Baum <Georg.Baum@post.rwth-aachen.de>
|
||||
|
||||
* 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 <Georg.Baum@post.rwth-aachen.de>
|
||||
|
||||
* math.C:
|
||||
|
@ -121,7 +121,7 @@ void parse_math(Parser & p, ostream & os, unsigned flags, const mode_type mode)
|
||||
}
|
||||
|
||||
else if (t.cat() == catComment) {
|
||||
if (t.cs().size())
|
||||
if (!t.cs().empty())
|
||||
cerr << "Ignoring comment: " << t.asInput();
|
||||
else
|
||||
// "%\n" combination
|
||||
|
@ -131,7 +131,7 @@ void handle_package(string const & name, string const & options)
|
||||
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, LyXTextClass const & /*textclass*/)
|
||||
<< "\\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 & p, ostream & os, string const & force
|
||||
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 & p, ostream & os, string const & force
|
||||
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 & p, ostream & os, string const & force
|
||||
}
|
||||
LyXTextClass textclass;
|
||||
textclass.Read(layoutfilename);
|
||||
if (! h_papersides.size()) {
|
||||
if (h_papersides.empty()) {
|
||||
ostringstream ss;
|
||||
ss << textclass.sides();
|
||||
h_papersides = ss.str();
|
||||
|
@ -299,7 +299,7 @@ void handle_tabular(Parser & p, ostream & os,
|
||||
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,
|
||||
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";
|
||||
}
|
||||
|
@ -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 const &)
|
||||
"\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, string const &)
|
||||
}
|
||||
|
||||
|
||||
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 const &)
|
||||
|
||||
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)
|
||||
{
|
||||
@ -267,6 +339,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]
|
||||
<< "\" for reading." << endl;
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <iosfwd>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
class Context;
|
||||
|
||||
@ -60,6 +61,15 @@ char const ** is_known(std::string const & str, char const ** what);
|
||||
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
|
||||
* be used more than once for included documents.
|
||||
|
@ -250,7 +250,7 @@ string Parser::getArg(char left, char right)
|
||||
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)
|
||||
|
@ -294,6 +294,43 @@ void check_space(Parser const & p, ostream & os, Context & context)
|
||||
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, ostream & os, bool outer,
|
||||
// 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, unsigned flags, bool outer,
|
||||
|
||||
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, unsigned flags, bool outer,
|
||||
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, unsigned flags, bool outer,
|
||||
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, unsigned flags, bool outer,
|
||||
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, unsigned flags, bool outer,
|
||||
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, unsigned flags, bool outer,
|
||||
// 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, unsigned flags, bool outer,
|
||||
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) {
|
||||
|
Loading…
Reference in New Issue
Block a user