]> git.lyx.org Git - lyx.git/blob - src/insets/ExternalTemplate.C
Enable the external inset to handle unknown templates gracefully.
[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
14 #include <algorithm>
15
16 #include "ExternalTemplate.h"
17
18 #include "lyxlex.h"
19 #include "debug.h"
20 #include "support/path.h"
21 #include "support/LAssert.h"
22 #include "support/filetools.h"
23
24 using std::endl;
25 using std::ostream;
26 using std::for_each;
27
28 extern string user_lyxdir;
29
30
31 // We have to have dummy default commands for security reasons!
32
33 ExternalTemplate::ExternalTemplate()
34         : inputFormat("*")
35 {}
36
37
38 ExternalTemplate::FormatTemplate::FormatTemplate()
39 {}
40
41
42 ExternalTemplateManager::ExternalTemplateManager()
43 {
44         // gimp gnuchess gnuplot ical netscape tetris xpaint
45         readTemplates(user_lyxdir);
46         if (lyxerr.debugging())
47                 dumpTemplates();
48 }
49
50
51 class dumpTemplate {
52 public:
53         dumpTemplate(ostream & o)
54                 : ost(o) {}
55         void operator()(ExternalTemplateManager::Templates::value_type const & vt) {
56                 ExternalTemplate const & et = vt.second;
57
58                 ost << "Template " << et.lyxName << "\n"
59                     << "\tGuiName " << et.guiName << "\n"
60                     << "\tHelpText\n"
61                     << et.helpText
62                     << "\tHelpTextEnd\n"
63                     << "\tInputFormat " << et.inputFormat << "\n"
64                     << "\tFileFilter " << et.fileRegExp << "\n"
65                     << "\tEditCommand " << et.editCommand << "\n"
66                     << "\tAutomaticProduction " << et.automaticProduction << "\n";
67                 et.dumpFormats(ost);
68                 ost << "TemplateEnd" << endl;
69
70         }
71
72 private:
73         ostream & ost;
74 };
75
76 class dumpFormat {
77 public:
78         dumpFormat(ostream & o)
79                 : ost(o) {}
80         void operator()(ExternalTemplate::Formats::value_type const & vt) const{
81                 ExternalTemplate::FormatTemplate const & ft = vt.second;
82                 ost << "\tFormat " << vt.first << "\n"
83                     << "\t\tProduct " << ft.product << "\n"
84                     << "\t\tUpdateFormat " << ft.updateFormat << "\n"
85                     << "\t\tUpdateResult " << ft.updateResult << "\n"
86                     << "\t\tRequirement " << ft.requirement << "\n"
87                     << "\t\tPreamble\n"
88                     << ft.preamble
89                     << "\t\tPreambleEnd\n"
90                     << "\tFormatEnd\n";
91         }
92 private:
93         ostream & ost;
94 };
95
96
97 void ExternalTemplate::dumpFormats(ostream & os) const
98 {
99         for_each(formats.begin(), formats.end(), dumpFormat(os));
100 }
101
102
103 void ExternalTemplateManager::dumpTemplates() const
104 {
105         for_each(templates.begin(), templates.end(), dumpTemplate(lyxerr));
106 }
107
108
109 ExternalTemplateManager & ExternalTemplateManager::get()
110 {
111         static ExternalTemplateManager externalTemplateManager;
112         return externalTemplateManager;
113 }
114
115
116 ExternalTemplateManager::Templates &
117 ExternalTemplateManager::getTemplates()
118 {
119         return templates;
120 }
121
122
123 ExternalTemplateManager::Templates const &
124 ExternalTemplateManager::getTemplates() const
125 {
126         return templates;
127 }
128
129
130 ExternalTemplate const & ExternalTemplateManager::getTemplateByName(string const & name)
131 {
132         return templates[name];
133 }
134
135
136 void ExternalTemplateManager::readTemplates(string const & path)
137 {
138         Path p(path);
139
140         enum TemplateTags {
141                 TM_TEMPLATE = 1,
142                 TM_END
143         };
144
145         keyword_item templatetags[] = {
146                 { "template", TM_TEMPLATE },
147                 { "templateend", TM_END }
148         };
149
150         string filename = LibFileSearch("", "external_templates");
151         if (filename.empty()) {
152                 lyxerr << "ExternalTemplateManager::readTemplates: "
153                         "No template file" << endl;
154                 return;
155         }
156
157         LyXLex lex(templatetags, TM_END);
158         if (!lex.setFile(filename)) {
159                 lyxerr << "ExternalTemplateManager::readTemplates: "
160                         "No template file" << endl;
161                 return;
162         }
163
164         while (lex.isOK()) {
165                 switch (lex.lex()) {
166                 case TM_TEMPLATE: {
167                         lex.next();
168                         string const temp = lex.getString();
169                         ExternalTemplate & tmp = templates[temp];
170                         tmp.lyxName = temp;
171                         tmp.readTemplate(lex);
172                 }
173                 break;
174
175                 case TM_END:
176                         lex.printError("Warning: End outside Template.");
177                 break;
178                 }
179         }
180 }
181
182
183 void ExternalTemplate::readTemplate(LyXLex & lex)
184 {
185         enum TemplateOptionTags {
186                 TO_GUINAME = 1,
187                 TO_HELPTEXT,
188                 TO_INPUTFORMAT,
189                 TO_FILTER,
190                 TO_EDITCMD,
191                 TO_AUTOMATIC,
192                 TO_FORMAT,
193                 TO_END
194         };
195
196         keyword_item templateoptiontags[] = {
197                 { "automaticproduction", TO_AUTOMATIC },
198                 { "editcommand", TO_EDITCMD },
199                 { "filefilter", TO_FILTER },
200                 { "format", TO_FORMAT },
201                 { "guiname", TO_GUINAME },
202                 { "helptext", TO_HELPTEXT },
203                 { "inputformat", TO_INPUTFORMAT },
204                 { "templateend", TO_END }
205         };
206
207         pushpophelper pph(lex, templateoptiontags, TO_END);
208
209         while (lex.isOK()) {
210                 switch (lex.lex()) {
211                 case TO_GUINAME:
212                         lex.next(true);
213                         guiName = lex.getString();
214                         break;
215
216                 case TO_HELPTEXT:
217                         helpText = lex.getLongString("HelpTextEnd");
218                         break;
219
220                 case TO_INPUTFORMAT:
221                         lex.next(true);
222                         inputFormat = lex.getString();
223                         break;
224
225                 case TO_FILTER:
226                         lex.next(true);
227                         fileRegExp = lex.getString();
228                         break;
229
230                 case TO_EDITCMD:
231                         lex.next(true);
232                         editCommand = lex.getString();
233                         break;
234
235                 case TO_AUTOMATIC:
236                         lex.next();
237                         automaticProduction = lex.getBool();
238                         break;
239
240                 case TO_FORMAT:
241                         lex.next(true);
242                         formats[lex.getString()].readFormat(lex);
243                         break;
244
245                 case TO_END:
246                         return;
247
248                 default:
249                         lex.printError("ExternalTemplate::readTemplate: "
250                                        "Wrong tag: $$Token");
251                         lyx::Assert(false);
252                         break;
253                 }
254         }
255 }
256
257
258 void ExternalTemplate::FormatTemplate::readFormat(LyXLex & lex)
259 {
260         enum FormatTags {
261                 FO_PRODUCT = 1,
262                 FO_UPDATEFORMAT,
263                 FO_UPDATERESULT,
264                 FO_REQUIREMENT,
265                 FO_PREAMBLE,
266                 FO_END
267         };
268
269         keyword_item formattags[] = {
270                 { "formatend", FO_END },
271                 { "preamble", FO_PREAMBLE },
272                 { "product", FO_PRODUCT },
273                 { "requirement", FO_REQUIREMENT },
274                 { "updateformat", FO_UPDATEFORMAT },
275                 { "updateresult", FO_UPDATERESULT }
276         };
277
278         pushpophelper pph(lex, formattags, FO_END);
279
280         while (lex.isOK()) {
281                 switch (lex.lex()) {
282                 case FO_PRODUCT:
283                         lex.next(true);
284                         product = lex.getString();
285                         break;
286
287                 case FO_UPDATEFORMAT:
288                         lex.next(true);
289                         updateFormat = lex.getString();
290                         break;
291
292                 case FO_UPDATERESULT:
293                         lex.next(true);
294                         updateResult = lex.getString();
295                         break;
296
297                 case FO_REQUIREMENT:
298                         lex.next(true);
299                         requirement = lex.getString();
300                         break;
301
302                 case FO_PREAMBLE:
303                         preamble = lex.getLongString("preambleend");
304                         break;
305
306                 case FO_END:
307                         if (lyxerr.debugging())
308                                 lex.printError("FormatEnd");
309                         return;
310                 }
311         }
312 }