]> git.lyx.org Git - lyx.git/blob - src/insets/ExternalTemplate.C
3c997c56baf1045b3d3d5e9c4bfe55662feae009
[lyx.git] / src / insets / ExternalTemplate.C
1 /**
2  * \file ExternalTemplate.C
3  * This file is part of LyX, the document processor.
4  * Licence details can be found in the file COPYING.
5  *
6  * \author Asger Alstrup Nielsen
7  *
8  * Full author contact details are available in file CREDITS.
9  */
10
11 #include <config.h>
12
13 #include "ExternalTemplate.h"
14
15 #include "debug.h"
16 #include "lyxlex.h"
17
18 #include "support/filetools.h"
19 #include "support/lstrings.h"
20 #include "support/path.h"
21 #include "support/path_defines.h"
22
23 #include <boost/assert.hpp>
24
25 #include <algorithm>
26
27 namespace support = lyx::support;
28
29 using std::endl;
30 using std::for_each;
31
32 using std::ostream;
33 using std::vector;
34
35
36 namespace lyx {
37 namespace external {
38
39 // We have to have dummy default commands for security reasons!
40 Template::Template()
41         : inputFormat("*")
42 {}
43
44
45 Template::Format::Format()
46 {}
47
48
49 TemplateManager::TemplateManager()
50 {
51         readTemplates(support::user_lyxdir());
52         if (lyxerr.debugging(Debug::EXTERNAL)) {
53                 dumpPreambleDefs(lyxerr);
54                 lyxerr << '\n';
55                 dumpTemplates(lyxerr);
56         }
57 }
58
59
60 class dumpPreambleDef {
61 public:
62         typedef TemplateManager::PreambleDefs::value_type value_type;
63
64         dumpPreambleDef(ostream & o) : ost(o) {}
65
66         void operator()(value_type const & vt) {
67                 ost << "PreambleDef " << vt.first << '\n'
68                     << vt.second
69                     << "PreambleDefEnd" << endl;
70         }
71
72 private:
73         ostream & ost;
74 };
75
76
77 class dumpTemplate {
78 public:
79         typedef TemplateManager::Templates::value_type value_type;
80
81         dumpTemplate(ostream & o) : ost(o) {}
82
83         void operator()(value_type const & vt) {
84                 Template const & et = vt.second;
85
86                 ost << "Template " << et.lyxName << '\n'
87                     << "\tGuiName " << et.guiName << '\n'
88                     << "\tHelpText\n"
89                     << et.helpText
90                     << "\tHelpTextEnd\n"
91                     << "\tInputFormat " << et.inputFormat << '\n'
92                     << "\tFileFilter " << et.fileRegExp << '\n'
93                     << "\tEditCommand " << et.editCommand << '\n'
94                     << "\tAutomaticProduction " << et.automaticProduction << '\n';
95                 et.dumpFormats(ost);
96                 ost << "TemplateEnd" << endl;
97
98         }
99
100 private:
101         ostream & ost;
102 };
103
104 class dumpFormat {
105 public:
106         typedef Template::Formats::value_type value_type;
107
108         dumpFormat(ostream & o) : ost(o) {}
109
110         void operator()(value_type const & vt) const{
111                 Template::Format const & ft = vt.second;
112                 ost << "\tFormat " << vt.first << '\n'
113                     << "\t\tProduct " << ft.product << '\n'
114                     << "\t\tUpdateFormat " << ft.updateFormat << '\n'
115                     << "\t\tUpdateResult " << ft.updateResult << '\n'
116                     << "\t\tRequirement " << ft.requirement << '\n';
117
118                 vector<string>::const_iterator it  = ft.preambleNames.begin();
119                 vector<string>::const_iterator end = ft.preambleNames.end();
120                 for (; it != end; ++it) {
121                         ost << "\t\tPreamble " << *it << '\n';
122                 }
123
124                 ost << "\tFormatEnd\n";
125         }
126 private:
127         ostream & ost;
128 };
129
130
131 void Template::dumpFormats(ostream & os) const
132 {
133         for_each(formats.begin(), formats.end(), dumpFormat(os));
134 }
135
136
137 void TemplateManager::dumpPreambleDefs(ostream & os) const
138 {
139         for_each(preambledefs.begin(), preambledefs.end(), dumpPreambleDef(os));
140 }
141
142
143 void TemplateManager::dumpTemplates(ostream & os) const
144 {
145         for_each(templates.begin(), templates.end(), dumpTemplate(os));
146 }
147
148
149 TemplateManager & TemplateManager::get()
150 {
151         static TemplateManager externalTemplateManager;
152         return externalTemplateManager;
153 }
154
155
156 TemplateManager::Templates &
157 TemplateManager::getTemplates()
158 {
159         return templates;
160 }
161
162
163 TemplateManager::Templates const &
164 TemplateManager::getTemplates() const
165 {
166         return templates;
167 }
168
169
170 Template const *
171 TemplateManager::getTemplateByName(string const & name) const
172 {
173         Templates::const_iterator it = templates.find(name);
174         return (it == templates.end()) ? 0 : &it->second;
175 }
176
177
178 string const
179 TemplateManager::getPreambleDefByName(string const & name) const
180 {
181         string const trimmed_name = support::trim(name);
182         if (trimmed_name.empty())
183                 return string();
184
185         PreambleDefs::const_iterator it = preambledefs.find(trimmed_name);
186         if (it == preambledefs.end())
187                 return string();
188
189         return it->second;
190 }
191
192
193 void TemplateManager::readTemplates(string const & path)
194 {
195         support::Path p(path);
196
197         enum TemplateTags {
198                 TM_PREAMBLEDEF = 1,
199                 TM_PREAMBLEDEF_END,
200                 TM_TEMPLATE,
201                 TM_TEMPLATE_END
202         };
203
204         keyword_item templatetags[] = {
205                 { "preambledef", TM_PREAMBLEDEF },
206                 { "preambledefend", TM_PREAMBLEDEF_END },
207                 { "template", TM_TEMPLATE },
208                 { "templateend", TM_TEMPLATE_END }
209         };
210
211         LyXLex lex(templatetags, TM_TEMPLATE_END);
212
213         string filename = support::LibFileSearch("", "external_templates");
214         if (filename.empty() || !lex.setFile(filename)) {
215                 lex.printError("external::TemplateManager::readTemplates: "
216                                "No template file");
217                 return;
218         }
219
220         char const * const preamble_end_tag =
221                 templatetags[TM_PREAMBLEDEF_END-1].tag;
222
223         while (lex.isOK()) {
224                 switch (lex.lex()) {
225                 case TM_PREAMBLEDEF: {
226                         lex.next();
227                         string const name = lex.getString();
228                         preambledefs[name] = lex.getLongString(preamble_end_tag);
229                 }
230                 break;
231
232                 case TM_TEMPLATE: {
233                         lex.next();
234                         string const name = lex.getString();
235                         Template & tmp = templates[name];
236                         tmp.lyxName = name;
237                         tmp.readTemplate(lex);
238                 }
239                 break;
240
241                 case TM_TEMPLATE_END:
242                         lex.printError("Warning: End outside Template.");
243                 break;
244
245                 case TM_PREAMBLEDEF_END:
246                         lex.printError("Warning: End outside PreambleDef.");
247                 break;
248                 }
249         }
250 }
251
252
253 void Template::readTemplate(LyXLex & lex)
254 {
255         enum TemplateOptionTags {
256                 TO_GUINAME = 1,
257                 TO_HELPTEXT,
258                 TO_INPUTFORMAT,
259                 TO_FILTER,
260                 TO_EDITCMD,
261                 TO_AUTOMATIC,
262                 TO_FORMAT,
263                 TO_END
264         };
265
266         keyword_item templateoptiontags[] = {
267                 { "automaticproduction", TO_AUTOMATIC },
268                 { "editcommand", TO_EDITCMD },
269                 { "filefilter", TO_FILTER },
270                 { "format", TO_FORMAT },
271                 { "guiname", TO_GUINAME },
272                 { "helptext", TO_HELPTEXT },
273                 { "inputformat", TO_INPUTFORMAT },
274                 { "templateend", TO_END }
275         };
276
277         pushpophelper pph(lex, templateoptiontags, TO_END);
278
279         while (lex.isOK()) {
280                 switch (lex.lex()) {
281                 case TO_GUINAME:
282                         lex.next(true);
283                         guiName = lex.getString();
284                         break;
285
286                 case TO_HELPTEXT:
287                         helpText = lex.getLongString("HelpTextEnd");
288                         break;
289
290                 case TO_INPUTFORMAT:
291                         lex.next(true);
292                         inputFormat = lex.getString();
293                         break;
294
295                 case TO_FILTER:
296                         lex.next(true);
297                         fileRegExp = lex.getString();
298                         break;
299
300                 case TO_EDITCMD:
301                         lex.next(true);
302                         editCommand = lex.getString();
303                         break;
304
305                 case TO_AUTOMATIC:
306                         lex.next();
307                         automaticProduction = lex.getBool();
308                         break;
309
310                 case TO_FORMAT:
311                         lex.next(true);
312                         formats[lex.getString()].readFormat(lex);
313                         break;
314
315                 case TO_END:
316                         return;
317
318                 default:
319                         lex.printError("external::Template::readTemplate: "
320                                        "Wrong tag: $$Token");
321                         BOOST_ASSERT(false);
322                         break;
323                 }
324         }
325 }
326
327
328 void Template::Format::readFormat(LyXLex & lex)
329 {
330         enum FormatTags {
331                 FO_PRODUCT = 1,
332                 FO_UPDATEFORMAT,
333                 FO_UPDATERESULT,
334                 FO_REQUIREMENT,
335                 FO_PREAMBLE,
336                 FO_END
337         };
338
339         keyword_item formattags[] = {
340                 { "formatend", FO_END },
341                 { "preamble", FO_PREAMBLE },
342                 { "product", FO_PRODUCT },
343                 { "requirement", FO_REQUIREMENT },
344                 { "updateformat", FO_UPDATEFORMAT },
345                 { "updateresult", FO_UPDATERESULT }
346         };
347
348         pushpophelper pph(lex, formattags, FO_END);
349
350         while (lex.isOK()) {
351                 switch (lex.lex()) {
352                 case FO_PRODUCT:
353                         lex.next(true);
354                         product = lex.getString();
355                         break;
356
357                 case FO_UPDATEFORMAT:
358                         lex.next(true);
359                         updateFormat = lex.getString();
360                         break;
361
362                 case FO_UPDATERESULT:
363                         lex.next(true);
364                         updateResult = lex.getString();
365                         break;
366
367                 case FO_REQUIREMENT:
368                         lex.next(true);
369                         requirement = lex.getString();
370                         break;
371
372                 case FO_PREAMBLE:
373                         lex.next(true);
374                         preambleNames.push_back(lex.getString());
375                         break;
376
377                 case FO_END:
378                         return;
379                 }
380         }
381 }
382
383 } // namespace external
384 } // namespace lyx