2 * \file ExternalTemplate.C
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Asger Alstrup Nielsen
7 * \author Angus Leeming
9 * Full author contact details are available in file CREDITS.
14 #include "ExternalTemplate.h"
19 #include "support/filetools.h"
20 #include "support/lstrings.h"
21 #include "support/path.h"
22 #include "support/path_defines.h"
23 #include "support/translator.h"
25 #include <boost/assert.hpp>
29 namespace support = lyx::support;
44 typedef Translator<TransformID, string> TransformIDTranslator;
45 TransformIDTranslator const & transformIDTranslator();
50 // We have to have dummy default commands for security reasons!
56 Template::Format::Format()
60 TemplateManager::TemplateManager()
62 readTemplates(support::user_lyxdir());
63 if (lyxerr.debugging(Debug::EXTERNAL)) {
64 dumpPreambleDefs(lyxerr);
66 dumpTemplates(lyxerr);
71 class dumpPreambleDef {
73 typedef TemplateManager::PreambleDefs::value_type value_type;
75 dumpPreambleDef(ostream & o) : ost(o) {}
77 void operator()(value_type const & vt) {
78 ost << "PreambleDef " << vt.first << '\n'
80 << "PreambleDefEnd" << endl;
90 typedef TemplateManager::Templates::value_type value_type;
92 dumpTemplate(ostream & o) : ost(o) {}
94 void operator()(value_type const & vt) {
95 Template const & et = vt.second;
97 ost << "Template " << et.lyxName << '\n'
98 << "\tGuiName " << et.guiName << '\n'
102 << "\tInputFormat " << et.inputFormat << '\n'
103 << "\tFileFilter " << et.fileRegExp << '\n'
104 << "\tEditCommand " << et.editCommand << '\n'
105 << "\tAutomaticProduction " << et.automaticProduction << '\n';
107 typedef vector<TransformID> IDs;
108 IDs::const_iterator it = et.transformIds.begin();
109 IDs::const_iterator end = et.transformIds.end();
110 for (; it != end; ++it) {
111 ost << "\tTransform "
112 << transformIDTranslator().find(*it) << '\n';
116 ost << "TemplateEnd" << endl;
126 typedef Template::Formats::value_type value_type;
128 dumpFormat(ostream & o) : ost(o) {}
130 void operator()(value_type const & vt) const {
131 Template::Format const & ft = vt.second;
132 ost << "\tFormat " << vt.first << '\n'
133 << "\t\tProduct " << ft.product << '\n'
134 << "\t\tUpdateFormat " << ft.updateFormat << '\n'
135 << "\t\tUpdateResult " << ft.updateResult << '\n'
136 << "\t\tRequirement " << ft.requirement << '\n';
138 typedef vector<Template::Option> Options;
139 Options::const_iterator oit = ft.options.begin();
140 Options::const_iterator oend = ft.options.end();
141 for (; oit != oend; ++oit) {
149 vector<string>::const_iterator pit = ft.preambleNames.begin();
150 vector<string>::const_iterator pend = ft.preambleNames.end();
151 for (; pit != pend; ++pit) {
152 ost << "\t\tPreamble " << *pit << '\n';
155 ost << "\tFormatEnd\n";
162 void Template::dumpFormats(ostream & os) const
164 for_each(formats.begin(), formats.end(), dumpFormat(os));
168 void TemplateManager::dumpPreambleDefs(ostream & os) const
170 for_each(preambledefs.begin(), preambledefs.end(), dumpPreambleDef(os));
174 void TemplateManager::dumpTemplates(ostream & os) const
176 for_each(templates.begin(), templates.end(), dumpTemplate(os));
180 TemplateManager & TemplateManager::get()
182 static TemplateManager externalTemplateManager;
183 return externalTemplateManager;
187 TemplateManager::Templates const &
188 TemplateManager::getTemplates() const
195 TemplateManager::getTemplateByName(string const & name) const
197 Templates::const_iterator it = templates.find(name);
198 return (it == templates.end()) ? 0 : &it->second;
203 TemplateManager::getPreambleDefByName(string const & name) const
205 string const trimmed_name = support::trim(name);
206 if (trimmed_name.empty())
209 PreambleDefs::const_iterator it = preambledefs.find(trimmed_name);
210 if (it == preambledefs.end())
217 void TemplateManager::readTemplates(string const & path)
219 support::Path p(path);
228 keyword_item templatetags[] = {
229 { "preambledef", TM_PREAMBLEDEF },
230 { "preambledefend", TM_PREAMBLEDEF_END },
231 { "template", TM_TEMPLATE },
232 { "templateend", TM_TEMPLATE_END }
235 LyXLex lex(templatetags, TM_TEMPLATE_END);
237 string filename = support::LibFileSearch("", "external_templates");
238 if (filename.empty() || !lex.setFile(filename)) {
239 lex.printError("external::TemplateManager::readTemplates: "
244 char const * const preamble_end_tag =
245 templatetags[TM_PREAMBLEDEF_END-1].tag;
249 case TM_PREAMBLEDEF: {
251 string const name = lex.getString();
252 preambledefs[name] = lex.getLongString(preamble_end_tag);
258 string const name = lex.getString();
259 Template & tmp = templates[name];
261 tmp.readTemplate(lex);
265 case TM_TEMPLATE_END:
266 lex.printError("Warning: End outside Template.");
269 case TM_PREAMBLEDEF_END:
270 lex.printError("Warning: End outside PreambleDef.");
279 void add(vector<TransformID> & ids, string const & name)
281 TransformID id = transformIDTranslator().find(name);
283 lyxerr << "external::Template::readTemplate\n"
284 << "Transform " << name << " is not recognized"
294 void Template::readTemplate(LyXLex & lex)
296 enum TemplateOptionTags {
308 keyword_item templateoptiontags[] = {
309 { "automaticproduction", TO_AUTOMATIC },
310 { "editcommand", TO_EDITCMD },
311 { "filefilter", TO_FILTER },
312 { "format", TO_FORMAT },
313 { "guiname", TO_GUINAME },
314 { "helptext", TO_HELPTEXT },
315 { "inputformat", TO_INPUTFORMAT },
316 { "templateend", TO_END },
317 { "transform", TO_TRANSFORM }
320 pushpophelper pph(lex, templateoptiontags, TO_END);
326 guiName = lex.getString();
330 helpText = lex.getLongString("HelpTextEnd");
335 inputFormat = lex.getString();
340 fileRegExp = lex.getString();
345 editCommand = lex.getString();
350 automaticProduction = lex.getBool();
355 add(transformIds, lex.getString());
360 formats[lex.getString()].readFormat(lex);
367 lex.printError("external::Template::readTemplate: "
368 "Wrong tag: $$Token");
378 void transform_not_found(std::ostream & os, string const & transform)
380 os << "external::Format::readFormat. Transformation \""
381 << transform << "\" is unrecognized." << std::endl;
385 void transform_class_not_found(std::ostream & os, string const & tclass)
387 os << "external::Format::readFormat. Transformation class \""
388 << tclass << "\" is unrecognized." << std::endl;
392 void setCommandFactory(Template::Format & format, string const & transform,
393 string const & transformer_class)
395 bool class_found = false;
396 if (transform == "Resize" && transformer_class == "ResizeLatexCommand") {
398 ResizeCommandFactory factory = ResizeLatexCommand::factory;
399 format.command_transformers[Resize] =
400 TransformStore(Resize, factory);
402 } else if (transform == "Rotate" &&
403 transformer_class == "RotationLatexCommand") {
405 RotationCommandFactory factory = RotationLatexCommand::factory;
406 format.command_transformers[Rotate] =
407 TransformStore(Rotate, factory);
410 transform_not_found(lyxerr, transform);
413 transform_class_not_found(lyxerr, transformer_class);
417 void setOptionFactory(Template::Format & format, string const & transform,
418 string const & transformer_class)
420 bool class_found = false;
421 if (transform == "Clip" && transformer_class == "ClipLatexOption") {
423 ClipOptionFactory factory = ClipLatexOption::factory;
424 format.option_transformers[Clip] =
425 TransformStore(Clip, factory);
427 } else if (transform == "Extra" && transformer_class == "ExtraOption") {
429 ExtraOptionFactory factory = ExtraOption::factory;
430 format.option_transformers[Extra] =
431 TransformStore(Extra, factory);
433 } else if (transform == "Resize" &&
434 transformer_class == "ResizeLatexOption") {
436 ResizeOptionFactory factory = ResizeLatexOption::factory;
437 format.option_transformers[Resize] =
438 TransformStore(Resize, factory);
440 } else if (transform == "Rotate" &&
441 transformer_class == "RotationLatexOption") {
443 RotationOptionFactory factory = RotationLatexOption::factory;
444 format.option_transformers[Rotate] =
445 TransformStore(Rotate, factory);
448 transform_not_found(lyxerr, transform);
451 transform_class_not_found(lyxerr, transformer_class);
457 void Template::Format::readFormat(LyXLex & lex)
471 keyword_item formattags[] = {
472 { "formatend", FO_END },
473 { "option", FO_OPTION },
474 { "preamble", FO_PREAMBLE },
475 { "product", FO_PRODUCT },
476 { "requirement", FO_REQUIREMENT },
477 { "transformcommand", FO_TRANSFORMCOMMAND },
478 { "transformoption", FO_TRANSFORMOPTION },
479 { "updateformat", FO_UPDATEFORMAT },
480 { "updateresult", FO_UPDATERESULT }
483 pushpophelper pph(lex, formattags, FO_END);
489 product = lex.getString();
492 case FO_UPDATEFORMAT:
494 updateFormat = lex.getString();
497 case FO_UPDATERESULT:
499 updateResult = lex.getString();
504 requirement = lex.getString();
509 preambleNames.push_back(lex.getString());
512 case FO_TRANSFORMCOMMAND: {
514 string const name = lex.getString();
516 setCommandFactory(*this, name, lex.getString());
520 case FO_TRANSFORMOPTION: {
522 string const name = lex.getString();
524 setOptionFactory(*this, name, lex.getString());
530 string const name = lex.getString();
532 string const opt = lex.getString();
533 options.push_back(Option(name, opt));
545 TransformIDTranslator const initIDTranslator()
547 TransformIDTranslator translator(TransformID(-1), "");
548 translator.addPair(Rotate, "Rotate");
549 translator.addPair(Resize, "Resize");
550 translator.addPair(Clip, "Clip");
551 translator.addPair(Extra, "Extra");
556 TransformIDTranslator const & transformIDTranslator()
558 static TransformIDTranslator const translator = initIDTranslator();
564 } // namespace external