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 "InsetHFill.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 InsetHFill::findInfo(cmdName);
155 return InsetHyperlink::findInfo(cmdName);
157 return InsetInclude::findInfo(cmdName);
158 case INDEX_PRINT_CODE:
159 return InsetPrintIndex::findInfo(cmdName);
161 return InsetLabel::findInfo(cmdName);
163 return InsetNomencl::findInfo(cmdName);
164 case NOMENCL_PRINT_CODE:
165 return InsetPrintNomencl::findInfo(cmdName);
167 return InsetRef::findInfo(cmdName);
169 return InsetTOC::findInfo(cmdName);
173 static const ParamInfo pi;
174 return pi; // to silence the warning
178 std::string InsetCommandParams::insetType() const
180 return insetName(insetCode_);
184 string InsetCommandParams::getDefaultCmd(InsetCode code) {
187 return InsetBibitem::defaultCommand();
189 return InsetBibtex::defaultCommand();
191 return InsetCitation::defaultCommand();
192 case FLOAT_LIST_CODE:
193 return InsetFloatList::defaultCommand();
195 return InsetHFill::defaultCommand();
197 return InsetHyperlink::defaultCommand();
199 return InsetInclude::defaultCommand();
200 case INDEX_PRINT_CODE:
201 return InsetPrintIndex::defaultCommand();
203 return InsetLabel::defaultCommand();
205 return InsetNomencl::defaultCommand();
206 case NOMENCL_PRINT_CODE:
207 return InsetPrintNomencl::defaultCommand();
209 return InsetRef::defaultCommand();
211 return InsetTOC::defaultCommand();
215 return string(); // silence the warning
219 bool InsetCommandParams::isCompatibleCommand(
220 InsetCode code, string const & s)
224 return InsetBibitem::isCompatibleCommand(s);
226 return InsetBibtex::isCompatibleCommand(s);
228 return InsetCitation::isCompatibleCommand(s);
229 case FLOAT_LIST_CODE:
230 return InsetFloatList::isCompatibleCommand(s);
232 return InsetHFill::isCompatibleCommand(s);
234 return InsetHyperlink::isCompatibleCommand(s);
236 return InsetInclude::isCompatibleCommand(s);
237 case INDEX_PRINT_CODE:
238 return InsetPrintIndex::isCompatibleCommand(s);
240 return InsetLabel::isCompatibleCommand(s);
242 return InsetNomencl::isCompatibleCommand(s);
243 case NOMENCL_PRINT_CODE:
244 return InsetPrintNomencl::isCompatibleCommand(s);
246 return InsetRef::isCompatibleCommand(s);
248 return InsetTOC::isCompatibleCommand(s);
252 return false; // silence the warning
256 void InsetCommandParams::setCmdName(string const & name)
258 if (!isCompatibleCommand(insetCode_, cmdName_)){
259 LYXERR0("InsetCommand: Incompatible command name " <<
261 throw ExceptionMessage(WarningException, _("InsetCommand Error: "),
262 _("Incompatible command name."));
266 info_ = findInfo(insetCode_, cmdName_);
270 void InsetCommandParams::read(Lexer & lex)
274 string const insetType = lex.getString();
275 InsetCode const code = insetCode(insetType);
276 if (code != insetCode_) {
277 lex.printError("InsetCommandParams: Attempt to change type of inset.");
278 throw ExceptionMessage(WarningException, _("InsetCommandParams Error: "),
279 _("Attempt to change type of parameters."));
285 string const test = lex.getString();
286 if (test != "LatexCommand") {
287 lex.printError("InsetCommandParams: No LatexCommand line found.");
288 throw ExceptionMessage(WarningException, _("InsetCommandParams error:"),
289 _("Can't find LatexCommand line."));
293 cmdName_ = lex.getString();
294 if (!isCompatibleCommand(insetCode_, cmdName_)){
295 lex.printError("InsetCommandParams: Incompatible command name " + cmdName_ + ".");
296 throw ExceptionMessage(WarningException, _("InsetCommandParams Error: "),
297 _("Incompatible command name."));
300 info_ = findInfo(insetCode_, cmdName_);
305 token = lex.getString();
306 if (token == "\\end_inset")
308 if (token == "preview") {
310 preview_ = lex.getBool();
313 if (info_.hasParam(token)) {
315 params_[token] = lex.getDocString();
317 lex.printError("Unknown parameter name `$$Token' for command " + cmdName_);
318 throw ExceptionMessage(WarningException,
319 _("InsetCommandParams: ") + from_ascii(cmdName_),
320 _("Unknown parameter name: ") + from_utf8(token));
323 if (token != "\\end_inset") {
324 lex.printError("Missing \\end_inset at this point. "
326 throw ExceptionMessage(WarningException,
327 _("Missing \\end_inset at this point."),
333 void InsetCommandParams::write(ostream & os) const
335 os << "CommandInset " << insetType() << '\n';
336 os << "LatexCommand " << cmdName_ << '\n';
338 os << "preview true\n";
339 ParamInfo::const_iterator it = info_.begin();
340 ParamInfo::const_iterator end = info_.end();
341 for (; it != end; ++it) {
342 std::string const & name = it->name();
343 docstring const & data = (*this)[name];
347 << Lexer::quoteString(to_utf8(data))
354 docstring InsetCommandParams::makeKeyValArgument() const
358 ParamInfo::const_iterator it = info_.begin();
359 ParamInfo::const_iterator end = info_.end();
360 for (; it != end; ++it) {
363 string const & name = it->name();
364 docstring const & data = (*this)[name];
371 os << from_utf8(name) << "=" << data;
377 bool InsetCommandParams::writeEmptyOptional(ParamInfo::const_iterator ci) const
379 if (!ci->isOptional())
381 ++ci; // we want to start with the next one
382 ParamInfo::const_iterator end = info_.end();
383 for (; ci != end; ++ci) {
384 switch (ci->type()) {
385 case ParamInfo::LATEX_KEY:
386 case ParamInfo::LYX_INTERNAL:
389 case ParamInfo::LATEX_REQUIRED:
390 case ParamInfo::LATEX_KV_REQUIRED:
393 case ParamInfo::LATEX_OPTIONAL: {
394 std::string const & name = ci->name();
395 docstring const & data = (*this)[name];
401 case ParamInfo::LATEX_KV_OPTIONAL: {
402 docstring data = makeKeyValArgument();
413 docstring const InsetCommandParams::getCommand() const
415 docstring s = '\\' + from_ascii(cmdName_);
417 ParamInfo::const_iterator it = info_.begin();
418 ParamInfo::const_iterator end = info_.end();
419 for (; it != end; ++it) {
420 std::string const & name = it->name();
421 switch (it->type()) {
422 case ParamInfo::LATEX_KEY:
423 case ParamInfo::LYX_INTERNAL:
426 case ParamInfo::LATEX_REQUIRED: {
427 docstring const & data = (*this)[name];
428 s += '{' + data + '}';
432 case ParamInfo::LATEX_KV_REQUIRED: {
433 s += "{" + makeKeyValArgument() + "}";
437 case ParamInfo::LATEX_OPTIONAL: {
438 docstring const & data = (*this)[name];
440 s += '[' + data + ']';
442 } else if (writeEmptyOptional(it)) {
448 case ParamInfo::LATEX_KV_OPTIONAL: {
449 docstring data = makeKeyValArgument();
451 s += '[' + data + ']';
453 } else if (writeEmptyOptional(it)) {
462 // Make sure that following stuff does not change the
469 docstring const InsetCommandParams::getFirstNonOptParam() const
471 ParamInfo::const_iterator it =
472 find_if(info_.begin(), info_.end(),
473 not1(mem_fun_ref(&ParamInfo::ParamData::isOptional)));
474 if (it == info_.end())
476 return (*this)[it->name()];
480 docstring const & InsetCommandParams::operator[](string const & name) const
482 static const docstring dummy; //so we don't return a ref to temporary
483 BOOST_ASSERT(info_.hasParam(name));
484 ParamMap::const_iterator data = params_.find(name);
485 if (data == params_.end() || data->second.empty())
491 docstring & InsetCommandParams::operator[](string const & name)
493 BOOST_ASSERT(info_.hasParam(name));
494 return params_[name];
498 void InsetCommandParams::clear()
504 bool operator==(InsetCommandParams const & o1,
505 InsetCommandParams const & o2)
507 return o1.insetCode_ == o2.insetCode_ &&
508 o1.cmdName_ == o2.cmdName_ &&
509 o1.info_ == o2.info_ &&
510 o1.params_ == o2.params_ &&
511 o1.preview_ == o2.preview_;
515 bool operator!=(InsetCommandParams const & o1,
516 InsetCommandParams const & o2)