2 * \file InsetCommandParams.cpp
3 * This file is part of LyX, the document processor.
4 * Licence details can be found in the file COPYING.
6 * \author Angus Leeming
10 * Full author contact details are available in file CREDITS.
16 #include "InsetCommandParams.h"
18 #include "InsetBibitem.h"
19 #include "InsetBibtex.h"
20 #include "InsetCitation.h"
21 #include "InsetFloatList.h"
22 #include "InsetHyperlink.h"
23 #include "InsetInclude.h"
24 #include "InsetIndex.h"
25 #include "InsetLabel.h"
26 #include "InsetNomencl.h"
32 #include "support/debug.h"
33 #include "support/docstream.h"
34 #include "support/ExceptionMessage.h"
35 #include "support/gettext.h"
36 #include "support/lstrings.h"
38 #include "support/lassert.h"
41 using namespace lyx::support;
46 /// Get information for \p code and command \p cmdName.
47 /// Returns 0 if the combination is not known. [FIXME: 0?]
48 /// Don't call this without first making sure the command name is
49 /// acceptable to the inset.
50 static ParamInfo const & findInfo(InsetCode code, string const & cmdName)
54 return InsetBibitem::findInfo(cmdName);
56 return InsetBibtex::findInfo(cmdName);
58 return InsetCitation::findInfo(cmdName);
60 return InsetFloatList::findInfo(cmdName);
62 return InsetHyperlink::findInfo(cmdName);
64 return InsetInclude::findInfo(cmdName);
65 case INDEX_PRINT_CODE:
66 return InsetPrintIndex::findInfo(cmdName);
68 return InsetLabel::findInfo(cmdName);
70 return InsetNomencl::findInfo(cmdName);
71 case NOMENCL_PRINT_CODE:
72 return InsetPrintNomencl::findInfo(cmdName);
74 return InsetRef::findInfo(cmdName);
76 return InsetTOC::findInfo(cmdName);
80 static const ParamInfo pi;
81 return pi; // to silence the warning
85 /////////////////////////////////////////////////////////////////////
87 // ParamInfo::ParamData
89 /////////////////////////////////////////////////////////////////////
91 ParamInfo::ParamData::ParamData(std::string const & s, ParamType t)
96 bool ParamInfo::ParamData::isOptional() const
98 return type_ == ParamInfo::LATEX_OPTIONAL;
102 bool ParamInfo::ParamData::operator==(ParamInfo::ParamData const & rhs) const
104 return name() == rhs.name() && type() == rhs.type();
108 bool ParamInfo::hasParam(std::string const & name) const
110 const_iterator it = begin();
111 const_iterator last = end();
112 for (; it != last; ++it) {
113 if (it->name() == name)
120 void ParamInfo::add(std::string const & name, ParamType type)
122 info_.push_back(ParamData(name, type));
126 bool ParamInfo::operator==(ParamInfo const & rhs) const
128 if (size() != rhs.size())
130 return equal(begin(), end(), rhs.begin());
134 ParamInfo::ParamData const &
135 ParamInfo::operator[](std::string const & name) const
137 LASSERT(hasParam(name), /**/);
138 const_iterator it = begin();
139 const_iterator last = end();
140 for (; it != last; ++it) {
141 if (it->name() == name)
144 return *it; // silence warning
148 /////////////////////////////////////////////////////////////////////
150 // InsetCommandParams
152 /////////////////////////////////////////////////////////////////////
155 InsetCommandParams::InsetCommandParams(InsetCode code)
156 : insetCode_(code), preview_(false)
158 cmdName_ = getDefaultCmd(code);
159 info_ = findInfo(code, cmdName_);
163 InsetCommandParams::InsetCommandParams(InsetCode code,
164 string const & cmdName)
165 : insetCode_(code), cmdName_(cmdName), preview_(false)
167 info_ = findInfo(code, cmdName);
171 std::string InsetCommandParams::insetType() const
173 return insetName(insetCode_);
177 string InsetCommandParams::getDefaultCmd(InsetCode code)
181 return InsetBibitem::defaultCommand();
183 return InsetBibtex::defaultCommand();
185 return InsetCitation::defaultCommand();
186 case FLOAT_LIST_CODE:
187 return InsetFloatList::defaultCommand();
189 return InsetHyperlink::defaultCommand();
191 return InsetInclude::defaultCommand();
192 case INDEX_PRINT_CODE:
193 return InsetPrintIndex::defaultCommand();
195 return InsetLabel::defaultCommand();
197 return InsetNomencl::defaultCommand();
198 case NOMENCL_PRINT_CODE:
199 return InsetPrintNomencl::defaultCommand();
201 return InsetRef::defaultCommand();
203 return InsetTOC::defaultCommand();
205 LASSERT(false, /**/);
207 return string(); // silence the warning
211 bool InsetCommandParams::isCompatibleCommand(InsetCode code, string const & s)
215 return InsetBibitem::isCompatibleCommand(s);
217 return InsetBibtex::isCompatibleCommand(s);
219 return InsetCitation::isCompatibleCommand(s);
220 case FLOAT_LIST_CODE:
221 return InsetFloatList::isCompatibleCommand(s);
223 return InsetHyperlink::isCompatibleCommand(s);
225 return InsetInclude::isCompatibleCommand(s);
226 case INDEX_PRINT_CODE:
227 return InsetPrintIndex::isCompatibleCommand(s);
229 return InsetLabel::isCompatibleCommand(s);
231 return InsetNomencl::isCompatibleCommand(s);
232 case NOMENCL_PRINT_CODE:
233 return InsetPrintNomencl::isCompatibleCommand(s);
235 return InsetRef::isCompatibleCommand(s);
237 return InsetTOC::isCompatibleCommand(s);
239 LASSERT(false, /**/);
241 return false; // silence the warning
245 void InsetCommandParams::setCmdName(string const & name)
247 if (!isCompatibleCommand(insetCode_, cmdName_)) {
248 LYXERR0("InsetCommand: Incompatible command name " <<
250 throw ExceptionMessage(WarningException, _("InsetCommand Error: "),
251 _("Incompatible command name."));
255 info_ = findInfo(insetCode_, cmdName_);
259 void InsetCommandParams::read(Lexer & lex)
261 lex.setContext("InsetCommandParams::read");
262 lex >> insetName(insetCode_).c_str();
263 lex >> "LatexCommand";
265 if (!isCompatibleCommand(insetCode_, cmdName_)) {
266 lex.printError("Incompatible command name " + cmdName_ + ".");
267 throw ExceptionMessage(WarningException, _("InsetCommandParams Error: "),
268 _("Incompatible command name."));
271 info_ = findInfo(insetCode_, cmdName_);
276 token = lex.getString();
277 if (token == "\\end_inset")
279 if (token == "preview") {
281 preview_ = lex.getBool();
284 if (info_.hasParam(token)) {
286 params_[token] = lex.getDocString();
288 lex.printError("Unknown parameter name `$$Token' for command " + cmdName_);
289 throw ExceptionMessage(WarningException,
290 _("InsetCommandParams: ") + from_ascii(cmdName_),
291 _("Unknown parameter name: ") + from_utf8(token));
294 if (token != "\\end_inset") {
295 lex.printError("Missing \\end_inset at this point. "
297 throw ExceptionMessage(WarningException,
298 _("InsetCommandParams Error: "),
299 _("Missing \\end_inset at this point: ") + from_utf8(token));
304 void InsetCommandParams::write(ostream & os) const
306 os << "CommandInset " << insetType() << '\n';
307 os << "LatexCommand " << cmdName_ << '\n';
309 os << "preview true\n";
310 ParamInfo::const_iterator it = info_.begin();
311 ParamInfo::const_iterator end = info_.end();
312 for (; it != end; ++it) {
313 std::string const & name = it->name();
314 docstring const & data = (*this)[name];
318 << Lexer::quoteString(to_utf8(data))
325 bool InsetCommandParams::writeEmptyOptional(ParamInfo::const_iterator ci) const
327 if (!ci->isOptional()) {
328 LASSERT(false, /**/);
330 ++ci; // we want to start with the next one
331 ParamInfo::const_iterator end = info_.end();
332 for (; ci != end; ++ci) {
333 switch (ci->type()) {
334 case ParamInfo::LYX_INTERNAL:
337 case ParamInfo::LATEX_REQUIRED:
340 case ParamInfo::LATEX_OPTIONAL: {
341 std::string const & name = ci->name();
342 docstring const & data = (*this)[name];
354 docstring InsetCommandParams::getCommand() const
356 docstring s = '\\' + from_ascii(cmdName_);
358 ParamInfo::const_iterator it = info_.begin();
359 ParamInfo::const_iterator end = info_.end();
360 for (; it != end; ++it) {
361 std::string const & name = it->name();
362 switch (it->type()) {
363 case ParamInfo::LYX_INTERNAL:
366 case ParamInfo::LATEX_REQUIRED: {
367 docstring const & data = (*this)[name];
368 s += '{' + data + '}';
372 case ParamInfo::LATEX_OPTIONAL: {
373 docstring const & data = (*this)[name];
375 s += '[' + data + ']';
377 } else if (writeEmptyOptional(it)) {
386 // Make sure that following stuff does not change the
393 docstring InsetCommandParams::getFirstNonOptParam() const
395 ParamInfo::const_iterator it =
396 find_if(info_.begin(), info_.end(),
397 not1(mem_fun_ref(&ParamInfo::ParamData::isOptional)));
398 if (it == info_.end()) {
399 LASSERT(false, return docstring());
401 return (*this)[it->name()];
405 docstring const & InsetCommandParams::operator[](string const & name) const
407 static const docstring dummy; //so we don't return a ref to temporary
408 LASSERT(info_.hasParam(name), return dummy);
409 ParamMap::const_iterator data = params_.find(name);
410 if (data == params_.end() || data->second.empty())
416 docstring & InsetCommandParams::operator[](string const & name)
418 LASSERT(info_.hasParam(name), /**/);
419 return params_[name];
423 void InsetCommandParams::clear()
429 bool operator==(InsetCommandParams const & o1, InsetCommandParams const & o2)
431 return o1.insetCode_ == o2.insetCode_
432 && o1.cmdName_ == o2.cmdName_
433 && o1.info_ == o2.info_
434 && o1.params_ == o2.params_
435 && o1.preview_ == o2.preview_;
439 bool operator!=(InsetCommandParams const & o1, InsetCommandParams const & o2)