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.
15 #include "InsetCommandParams.h"
17 #include "InsetBibitem.h"
18 #include "InsetBibtex.h"
19 #include "InsetCitation.h"
20 #include "InsetFloatList.h"
21 #include "InsetHyperlink.h"
22 #include "InsetInclude.h"
23 #include "InsetIndex.h"
24 #include "InsetLabel.h"
25 #include "InsetNomencl.h"
31 #include "support/debug.h"
32 #include "support/docstream.h"
33 #include "support/ExceptionMessage.h"
34 #include "support/gettext.h"
35 #include "support/lstrings.h"
37 #include <boost/assert.hpp>
40 using namespace lyx::support;
45 /////////////////////////////////////////////////////////////////////
47 // ParamInfo::ParamData
49 /////////////////////////////////////////////////////////////////////
51 ParamInfo::ParamData::ParamData(std::string const & s, ParamType t)
56 bool ParamInfo::ParamData::isOptional() const
58 return type_ == ParamInfo::LATEX_OPTIONAL
59 || type_ == ParamInfo::LATEX_KV_OPTIONAL;
63 bool ParamInfo::ParamData::isKeyValArg() const
65 return type_ == ParamInfo::LATEX_KV_REQUIRED
66 || type_ == ParamInfo::LATEX_KV_OPTIONAL;
70 bool ParamInfo::ParamData::operator==(ParamInfo::ParamData const & rhs) const
72 return name() == rhs.name() && type() == rhs.type();
76 bool ParamInfo::hasParam(std::string const & name) const
78 const_iterator it = begin();
79 const_iterator last = end();
80 for (; it != last; ++it) {
81 if (it->name() == name)
82 return !it->isKeyValArg();
88 void ParamInfo::add(std::string const & name, ParamType type)
90 info_.push_back(ParamData(name, type));
94 bool ParamInfo::operator==(ParamInfo const & rhs) const
96 if (size() != rhs.size())
98 return equal(begin(), end(), rhs.begin());
102 ParamInfo::ParamData const &
103 ParamInfo::operator[](std::string const & name) const
105 BOOST_ASSERT(hasParam(name));
106 const_iterator it = begin();
107 const_iterator last = end();
108 for (; it != last; ++it) {
109 if (it->name() == name)
112 return *it; // silence warning
116 /////////////////////////////////////////////////////////////////////
118 // InsetCommandParams
120 /////////////////////////////////////////////////////////////////////
123 InsetCommandParams::InsetCommandParams(InsetCode code)
124 : insetCode_(code), preview_(false)
126 cmdName_ = getDefaultCmd(code);
127 info_ = findInfo(code, cmdName_);
131 InsetCommandParams::InsetCommandParams(InsetCode code,
132 string const & cmdName)
133 : insetCode_(code), cmdName_(cmdName), preview_(false)
135 info_ = findInfo(code, cmdName);
139 ParamInfo const & InsetCommandParams::findInfo(
140 InsetCode code, string const & cmdName)
144 return InsetBibitem::findInfo(cmdName);
146 return InsetBibtex::findInfo(cmdName);
148 return InsetCitation::findInfo(cmdName);
149 case FLOAT_LIST_CODE:
150 return InsetFloatList::findInfo(cmdName);
152 return InsetHyperlink::findInfo(cmdName);
154 return InsetInclude::findInfo(cmdName);
155 case INDEX_PRINT_CODE:
156 return InsetPrintIndex::findInfo(cmdName);
158 return InsetLabel::findInfo(cmdName);
160 return InsetNomencl::findInfo(cmdName);
161 case NOMENCL_PRINT_CODE:
162 return InsetPrintNomencl::findInfo(cmdName);
164 return InsetRef::findInfo(cmdName);
166 return InsetTOC::findInfo(cmdName);
170 static const ParamInfo pi;
171 return pi; // to silence the warning
175 std::string InsetCommandParams::insetType() const
177 return insetName(insetCode_);
181 string InsetCommandParams::getDefaultCmd(InsetCode code) {
184 return InsetBibitem::defaultCommand();
186 return InsetBibtex::defaultCommand();
188 return InsetCitation::defaultCommand();
189 case FLOAT_LIST_CODE:
190 return InsetFloatList::defaultCommand();
192 return InsetHyperlink::defaultCommand();
194 return InsetInclude::defaultCommand();
195 case INDEX_PRINT_CODE:
196 return InsetPrintIndex::defaultCommand();
198 return InsetLabel::defaultCommand();
200 return InsetNomencl::defaultCommand();
201 case NOMENCL_PRINT_CODE:
202 return InsetPrintNomencl::defaultCommand();
204 return InsetRef::defaultCommand();
206 return InsetTOC::defaultCommand();
210 return string(); // silence the warning
214 bool InsetCommandParams::isCompatibleCommand(
215 InsetCode code, string const & s)
219 return InsetBibitem::isCompatibleCommand(s);
221 return InsetBibtex::isCompatibleCommand(s);
223 return InsetCitation::isCompatibleCommand(s);
224 case FLOAT_LIST_CODE:
225 return InsetFloatList::isCompatibleCommand(s);
227 return InsetHyperlink::isCompatibleCommand(s);
229 return InsetInclude::isCompatibleCommand(s);
230 case INDEX_PRINT_CODE:
231 return InsetPrintIndex::isCompatibleCommand(s);
233 return InsetLabel::isCompatibleCommand(s);
235 return InsetNomencl::isCompatibleCommand(s);
236 case NOMENCL_PRINT_CODE:
237 return InsetPrintNomencl::isCompatibleCommand(s);
239 return InsetRef::isCompatibleCommand(s);
241 return InsetTOC::isCompatibleCommand(s);
245 return false; // silence the warning
249 void InsetCommandParams::setCmdName(string const & name)
251 if (!isCompatibleCommand(insetCode_, cmdName_)){
252 LYXERR0("InsetCommand: Incompatible command name " <<
254 throw ExceptionMessage(WarningException, _("InsetCommand Error: "),
255 _("Incompatible command name."));
259 info_ = findInfo(insetCode_, cmdName_);
263 void InsetCommandParams::read(Lexer & lex)
267 string const insetType = lex.getString();
268 InsetCode const code = insetCode(insetType);
269 if (code != insetCode_) {
270 lex.printError("InsetCommandParams: Attempt to change type of inset.");
271 throw ExceptionMessage(WarningException, _("InsetCommandParams Error: "),
272 _("Attempt to change type of parameters."));
278 string const test = lex.getString();
279 if (test != "LatexCommand") {
280 lex.printError("InsetCommandParams: No LatexCommand line found.");
281 throw ExceptionMessage(WarningException, _("InsetCommandParams error:"),
282 _("Can't find LatexCommand line."));
286 cmdName_ = lex.getString();
287 if (!isCompatibleCommand(insetCode_, cmdName_)){
288 lex.printError("InsetCommandParams: Incompatible command name " + cmdName_ + ".");
289 throw ExceptionMessage(WarningException, _("InsetCommandParams Error: "),
290 _("Incompatible command name."));
293 info_ = findInfo(insetCode_, cmdName_);
298 token = lex.getString();
299 if (token == "\\end_inset")
301 if (token == "preview") {
303 preview_ = lex.getBool();
306 if (info_.hasParam(token)) {
308 params_[token] = lex.getDocString();
310 lex.printError("Unknown parameter name `$$Token' for command " + cmdName_);
311 throw ExceptionMessage(WarningException,
312 _("InsetCommandParams: ") + from_ascii(cmdName_),
313 _("Unknown parameter name: ") + from_utf8(token));
316 if (token != "\\end_inset") {
317 lex.printError("Missing \\end_inset at this point. "
319 throw ExceptionMessage(WarningException,
320 _("Missing \\end_inset at this point."),
326 void InsetCommandParams::write(ostream & os) const
328 os << "CommandInset " << insetType() << '\n';
329 os << "LatexCommand " << cmdName_ << '\n';
331 os << "preview true\n";
332 ParamInfo::const_iterator it = info_.begin();
333 ParamInfo::const_iterator end = info_.end();
334 for (; it != end; ++it) {
335 std::string const & name = it->name();
336 docstring const & data = (*this)[name];
340 << Lexer::quoteString(to_utf8(data))
347 docstring InsetCommandParams::makeKeyValArgument() const
351 ParamInfo::const_iterator it = info_.begin();
352 ParamInfo::const_iterator end = info_.end();
353 for (; it != end; ++it) {
356 string const & name = it->name();
357 docstring const & data = (*this)[name];
364 os << from_utf8(name) << "=" << data;
370 bool InsetCommandParams::writeEmptyOptional(ParamInfo::const_iterator ci) const
372 if (!ci->isOptional())
374 ++ci; // we want to start with the next one
375 ParamInfo::const_iterator end = info_.end();
376 for (; ci != end; ++ci) {
377 switch (ci->type()) {
378 case ParamInfo::LATEX_KEY:
379 case ParamInfo::LYX_INTERNAL:
382 case ParamInfo::LATEX_REQUIRED:
383 case ParamInfo::LATEX_KV_REQUIRED:
386 case ParamInfo::LATEX_OPTIONAL: {
387 std::string const & name = ci->name();
388 docstring const & data = (*this)[name];
394 case ParamInfo::LATEX_KV_OPTIONAL: {
395 docstring data = makeKeyValArgument();
406 docstring const InsetCommandParams::getCommand() const
408 docstring s = '\\' + from_ascii(cmdName_);
410 ParamInfo::const_iterator it = info_.begin();
411 ParamInfo::const_iterator end = info_.end();
412 for (; it != end; ++it) {
413 std::string const & name = it->name();
414 switch (it->type()) {
415 case ParamInfo::LATEX_KEY:
416 case ParamInfo::LYX_INTERNAL:
419 case ParamInfo::LATEX_REQUIRED: {
420 docstring const & data = (*this)[name];
421 s += '{' + data + '}';
425 case ParamInfo::LATEX_KV_REQUIRED: {
426 s += "{" + makeKeyValArgument() + "}";
430 case ParamInfo::LATEX_OPTIONAL: {
431 docstring const & data = (*this)[name];
433 s += '[' + data + ']';
435 } else if (writeEmptyOptional(it)) {
441 case ParamInfo::LATEX_KV_OPTIONAL: {
442 docstring data = makeKeyValArgument();
444 s += '[' + data + ']';
446 } else if (writeEmptyOptional(it)) {
455 // Make sure that following stuff does not change the
462 docstring const InsetCommandParams::getFirstNonOptParam() const
464 ParamInfo::const_iterator it =
465 find_if(info_.begin(), info_.end(),
466 not1(mem_fun_ref(&ParamInfo::ParamData::isOptional)));
467 if (it == info_.end())
469 return (*this)[it->name()];
473 docstring const & InsetCommandParams::operator[](string const & name) const
475 static const docstring dummy; //so we don't return a ref to temporary
476 BOOST_ASSERT(info_.hasParam(name));
477 ParamMap::const_iterator data = params_.find(name);
478 if (data == params_.end() || data->second.empty())
484 docstring & InsetCommandParams::operator[](string const & name)
486 BOOST_ASSERT(info_.hasParam(name));
487 return params_[name];
491 void InsetCommandParams::clear()
497 bool operator==(InsetCommandParams const & o1,
498 InsetCommandParams const & o2)
500 return o1.insetCode_ == o2.insetCode_ &&
501 o1.cmdName_ == o2.cmdName_ &&
502 o1.info_ == o2.info_ &&
503 o1.params_ == o2.params_ &&
504 o1.preview_ == o2.preview_;
508 bool operator!=(InsetCommandParams const & o1,
509 InsetCommandParams const & o2)