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 <boost/assert.hpp>
41 using namespace lyx::support;
46 /////////////////////////////////////////////////////////////////////
48 // ParamInfo::ParamData
50 /////////////////////////////////////////////////////////////////////
52 ParamInfo::ParamData::ParamData(std::string const & s, ParamType t)
57 bool ParamInfo::ParamData::isOptional() const
59 return type_ == ParamInfo::LATEX_OPTIONAL
60 || type_ == ParamInfo::LATEX_KV_OPTIONAL;
64 bool ParamInfo::ParamData::isKeyValArg() const
66 return type_ == ParamInfo::LATEX_KV_REQUIRED
67 || type_ == ParamInfo::LATEX_KV_OPTIONAL;
71 bool ParamInfo::ParamData::operator==(ParamInfo::ParamData const & rhs) const
73 return name() == rhs.name() && type() == rhs.type();
77 bool ParamInfo::hasParam(std::string const & name) const
79 const_iterator it = begin();
80 const_iterator last = end();
81 for (; it != last; ++it) {
82 if (it->name() == name)
83 return !it->isKeyValArg();
89 void ParamInfo::add(std::string const & name, ParamType type)
91 info_.push_back(ParamData(name, type));
95 bool ParamInfo::operator==(ParamInfo const & rhs) const
97 if (size() != rhs.size())
99 return equal(begin(), end(), rhs.begin());
103 ParamInfo::ParamData const &
104 ParamInfo::operator[](std::string const & name) const
106 BOOST_ASSERT(hasParam(name));
107 const_iterator it = begin();
108 const_iterator last = end();
109 for (; it != last; ++it) {
110 if (it->name() == name)
113 return *it; // silence warning
117 /////////////////////////////////////////////////////////////////////
119 // InsetCommandParams
121 /////////////////////////////////////////////////////////////////////
124 InsetCommandParams::InsetCommandParams(InsetCode code)
125 : insetCode_(code), preview_(false)
127 cmdName_ = getDefaultCmd(code);
128 info_ = findInfo(code, cmdName_);
132 InsetCommandParams::InsetCommandParams(InsetCode code,
133 string const & cmdName)
134 : insetCode_(code), cmdName_(cmdName), preview_(false)
136 info_ = findInfo(code, cmdName);
140 ParamInfo const & InsetCommandParams::findInfo(
141 InsetCode code, string const & cmdName)
145 return InsetBibitem::findInfo(cmdName);
147 return InsetBibtex::findInfo(cmdName);
149 return InsetCitation::findInfo(cmdName);
150 case FLOAT_LIST_CODE:
151 return InsetFloatList::findInfo(cmdName);
153 return InsetHyperlink::findInfo(cmdName);
155 return InsetInclude::findInfo(cmdName);
156 case INDEX_PRINT_CODE:
157 return InsetPrintIndex::findInfo(cmdName);
159 return InsetLabel::findInfo(cmdName);
161 return InsetNomencl::findInfo(cmdName);
162 case NOMENCL_PRINT_CODE:
163 return InsetPrintNomencl::findInfo(cmdName);
165 return InsetRef::findInfo(cmdName);
167 return InsetTOC::findInfo(cmdName);
171 static const ParamInfo pi;
172 return pi; // to silence the warning
176 std::string InsetCommandParams::insetType() const
178 return insetName(insetCode_);
182 string InsetCommandParams::getDefaultCmd(InsetCode code) {
185 return InsetBibitem::defaultCommand();
187 return InsetBibtex::defaultCommand();
189 return InsetCitation::defaultCommand();
190 case FLOAT_LIST_CODE:
191 return InsetFloatList::defaultCommand();
193 return InsetHyperlink::defaultCommand();
195 return InsetInclude::defaultCommand();
196 case INDEX_PRINT_CODE:
197 return InsetPrintIndex::defaultCommand();
199 return InsetLabel::defaultCommand();
201 return InsetNomencl::defaultCommand();
202 case NOMENCL_PRINT_CODE:
203 return InsetPrintNomencl::defaultCommand();
205 return InsetRef::defaultCommand();
207 return InsetTOC::defaultCommand();
211 return string(); // silence the warning
215 bool InsetCommandParams::isCompatibleCommand(
216 InsetCode code, string const & s)
220 return InsetBibitem::isCompatibleCommand(s);
222 return InsetBibtex::isCompatibleCommand(s);
224 return InsetCitation::isCompatibleCommand(s);
225 case FLOAT_LIST_CODE:
226 return InsetFloatList::isCompatibleCommand(s);
228 return InsetHyperlink::isCompatibleCommand(s);
230 return InsetInclude::isCompatibleCommand(s);
231 case INDEX_PRINT_CODE:
232 return InsetPrintIndex::isCompatibleCommand(s);
234 return InsetLabel::isCompatibleCommand(s);
236 return InsetNomencl::isCompatibleCommand(s);
237 case NOMENCL_PRINT_CODE:
238 return InsetPrintNomencl::isCompatibleCommand(s);
240 return InsetRef::isCompatibleCommand(s);
242 return InsetTOC::isCompatibleCommand(s);
246 return false; // silence the warning
250 void InsetCommandParams::setCmdName(string const & name)
252 if (!isCompatibleCommand(insetCode_, cmdName_)){
253 LYXERR0("InsetCommand: Incompatible command name " <<
255 throw ExceptionMessage(WarningException, _("InsetCommand Error: "),
256 _("Incompatible command name."));
260 info_ = findInfo(insetCode_, cmdName_);
264 void InsetCommandParams::read(Lexer & lex)
268 string const insetType = lex.getString();
269 InsetCode const code = insetCode(insetType);
270 if (code != insetCode_) {
271 lex.printError("InsetCommandParams: Attempt to change type of inset.");
272 throw ExceptionMessage(WarningException, _("InsetCommandParams Error: "),
273 _("Attempt to change type of parameters."));
279 string const test = lex.getString();
280 if (test != "LatexCommand") {
281 lex.printError("InsetCommandParams: No LatexCommand line found.");
282 throw ExceptionMessage(WarningException, _("InsetCommandParams error: "),
283 _("Can't find LatexCommand line."));
287 cmdName_ = lex.getString();
288 if (!isCompatibleCommand(insetCode_, cmdName_)){
289 lex.printError("InsetCommandParams: Incompatible command name " + cmdName_ + ".");
290 throw ExceptionMessage(WarningException, _("InsetCommandParams Error: "),
291 _("Incompatible command name."));
294 info_ = findInfo(insetCode_, cmdName_);
299 token = lex.getString();
300 if (token == "\\end_inset")
302 if (token == "preview") {
304 preview_ = lex.getBool();
307 if (info_.hasParam(token)) {
309 params_[token] = lex.getDocString();
311 lex.printError("Unknown parameter name `$$Token' for command " + cmdName_);
312 throw ExceptionMessage(WarningException,
313 _("InsetCommandParams: ") + from_ascii(cmdName_),
314 _("Unknown parameter name: ") + from_utf8(token));
317 if (token != "\\end_inset") {
318 lex.printError("Missing \\end_inset at this point. "
320 throw ExceptionMessage(WarningException,
321 _("Missing \\end_inset at this point."),
327 void InsetCommandParams::write(ostream & os) const
329 os << "CommandInset " << insetType() << '\n';
330 os << "LatexCommand " << cmdName_ << '\n';
332 os << "preview true\n";
333 ParamInfo::const_iterator it = info_.begin();
334 ParamInfo::const_iterator end = info_.end();
335 for (; it != end; ++it) {
336 std::string const & name = it->name();
337 docstring const & data = (*this)[name];
341 << Lexer::quoteString(to_utf8(data))
348 docstring InsetCommandParams::makeKeyValArgument() const
352 ParamInfo::const_iterator it = info_.begin();
353 ParamInfo::const_iterator end = info_.end();
354 for (; it != end; ++it) {
357 string const & name = it->name();
358 docstring const & data = (*this)[name];
365 os << from_utf8(name) << "=" << data;
371 bool InsetCommandParams::writeEmptyOptional(ParamInfo::const_iterator ci) const
373 if (!ci->isOptional())
375 ++ci; // we want to start with the next one
376 ParamInfo::const_iterator end = info_.end();
377 for (; ci != end; ++ci) {
378 switch (ci->type()) {
379 case ParamInfo::LATEX_KEY:
380 case ParamInfo::LYX_INTERNAL:
383 case ParamInfo::LATEX_REQUIRED:
384 case ParamInfo::LATEX_KV_REQUIRED:
387 case ParamInfo::LATEX_OPTIONAL: {
388 std::string const & name = ci->name();
389 docstring const & data = (*this)[name];
395 case ParamInfo::LATEX_KV_OPTIONAL: {
396 docstring data = makeKeyValArgument();
407 docstring const InsetCommandParams::getCommand() const
409 docstring s = '\\' + from_ascii(cmdName_);
411 ParamInfo::const_iterator it = info_.begin();
412 ParamInfo::const_iterator end = info_.end();
413 for (; it != end; ++it) {
414 std::string const & name = it->name();
415 switch (it->type()) {
416 case ParamInfo::LATEX_KEY:
417 case ParamInfo::LYX_INTERNAL:
420 case ParamInfo::LATEX_REQUIRED: {
421 docstring const & data = (*this)[name];
422 s += '{' + data + '}';
426 case ParamInfo::LATEX_KV_REQUIRED: {
427 s += "{" + makeKeyValArgument() + "}";
431 case ParamInfo::LATEX_OPTIONAL: {
432 docstring const & data = (*this)[name];
434 s += '[' + data + ']';
436 } else if (writeEmptyOptional(it)) {
442 case ParamInfo::LATEX_KV_OPTIONAL: {
443 docstring data = makeKeyValArgument();
445 s += '[' + data + ']';
447 } else if (writeEmptyOptional(it)) {
456 // Make sure that following stuff does not change the
463 docstring const InsetCommandParams::getFirstNonOptParam() const
465 ParamInfo::const_iterator it =
466 find_if(info_.begin(), info_.end(),
467 not1(mem_fun_ref(&ParamInfo::ParamData::isOptional)));
468 if (it == info_.end())
470 return (*this)[it->name()];
474 docstring const & InsetCommandParams::operator[](string const & name) const
476 static const docstring dummy; //so we don't return a ref to temporary
477 BOOST_ASSERT(info_.hasParam(name));
478 ParamMap::const_iterator data = params_.find(name);
479 if (data == params_.end() || data->second.empty())
485 docstring & InsetCommandParams::operator[](string const & name)
487 BOOST_ASSERT(info_.hasParam(name));
488 return params_[name];
492 void InsetCommandParams::clear()
498 bool operator==(InsetCommandParams const & o1,
499 InsetCommandParams const & o2)
501 return o1.insetCode_ == o2.insetCode_ &&
502 o1.cmdName_ == o2.cmdName_ &&
503 o1.info_ == o2.info_ &&
504 o1.params_ == o2.params_ &&
505 o1.preview_ == o2.preview_;
509 bool operator!=(InsetCommandParams const & o1,
510 InsetCommandParams const & o2)