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/ExceptionMessage.h"
34 #include "support/gettext.h"
35 #include "support/lstrings.h"
36 #include "support/docstream.h"
38 #include <boost/assert.hpp>
41 using namespace lyx::support;
45 ParamInfo::ParamData::ParamData(std::string const & s, bool b) :
46 name_(s), optional_(b)
50 bool ParamInfo::ParamData::operator==(ParamInfo::ParamData const & rhs) const
52 return name() == rhs.name() && isOptional() == rhs.isOptional();
56 bool ParamInfo::hasParam(std::string const & name) const
58 const_iterator it = begin();
59 for (; it != end(); ++it) {
60 if (it->name() == name)
67 void ParamInfo::add(std::string const & name, bool opt)
69 info_.push_back(ParamData(name, opt));
73 bool ParamInfo::operator==(ParamInfo const & rhs) const
75 // the idea here is to check each ParamData for equality
76 const_iterator itL = begin();
77 const_iterator itR = rhs.begin();
78 const_iterator endL = end();
79 const_iterator endR = rhs.end();
81 // if they both end together, return true
82 if (itL == endL && itR == endR)
84 // but if one ends before the other, return false
85 if (itL == endL || itR == endR)
87 //check this one for equality
90 // equal, so check the next one
97 InsetCommandParams::InsetCommandParams(InsetCode code)
98 : insetCode_(code), preview_(false)
100 cmdName_ = getDefaultCmd(code);
101 info_ = findInfo(code, cmdName_);
105 InsetCommandParams::InsetCommandParams(InsetCode code,
106 string const & cmdName)
107 : insetCode_(code), cmdName_(cmdName), preview_(false)
109 info_ = findInfo(code, cmdName);
113 ParamInfo const & InsetCommandParams::findInfo(
114 InsetCode code, string const & cmdName)
118 return InsetBibitem::findInfo(cmdName);
120 return InsetBibtex::findInfo(cmdName);
122 return InsetCitation::findInfo(cmdName);
123 case FLOAT_LIST_CODE:
124 return InsetFloatList::findInfo(cmdName);
126 return InsetHFill::findInfo(cmdName);
128 return InsetHyperlink::findInfo(cmdName);
130 return InsetInclude::findInfo(cmdName);
131 case INDEX_PRINT_CODE:
132 return InsetPrintIndex::findInfo(cmdName);
134 return InsetLabel::findInfo(cmdName);
136 return InsetNomencl::findInfo(cmdName);
137 case NOMENCL_PRINT_CODE:
138 return InsetPrintNomencl::findInfo(cmdName);
140 return InsetRef::findInfo(cmdName);
142 return InsetTOC::findInfo(cmdName);
146 static const ParamInfo pi;
147 return pi; // to silence the warning
151 string InsetCommandParams::getDefaultCmd(InsetCode code) {
154 return InsetBibitem::defaultCommand();
156 return InsetBibtex::defaultCommand();
158 return InsetCitation::defaultCommand();
159 case FLOAT_LIST_CODE:
160 return InsetFloatList::defaultCommand();
162 return InsetHFill::defaultCommand();
164 return InsetHyperlink::defaultCommand();
166 return InsetInclude::defaultCommand();
167 case INDEX_PRINT_CODE:
168 return InsetPrintIndex::defaultCommand();
170 return InsetLabel::defaultCommand();
172 return InsetNomencl::defaultCommand();
173 case NOMENCL_PRINT_CODE:
174 return InsetPrintNomencl::defaultCommand();
176 return InsetRef::defaultCommand();
178 return InsetTOC::defaultCommand();
182 return string(); // silence the warning
186 bool InsetCommandParams::isCompatibleCommand(
187 InsetCode code, string const & s)
191 return InsetBibitem::isCompatibleCommand(s);
193 return InsetBibtex::isCompatibleCommand(s);
195 return InsetCitation::isCompatibleCommand(s);
196 case FLOAT_LIST_CODE:
197 return InsetFloatList::isCompatibleCommand(s);
199 return InsetHFill::isCompatibleCommand(s);
201 return InsetHyperlink::isCompatibleCommand(s);
203 return InsetInclude::isCompatibleCommand(s);
204 case INDEX_PRINT_CODE:
205 return InsetPrintIndex::isCompatibleCommand(s);
207 return InsetLabel::isCompatibleCommand(s);
209 return InsetNomencl::isCompatibleCommand(s);
210 case NOMENCL_PRINT_CODE:
211 return InsetPrintNomencl::isCompatibleCommand(s);
213 return InsetRef::isCompatibleCommand(s);
215 return InsetTOC::isCompatibleCommand(s);
219 return false; // silence the warning
223 void InsetCommandParams::setCmdName(string const & name)
225 if (!isCompatibleCommand(insetCode_, cmdName_)){
226 LYXERR0("InsetCommand: Incompatible command name " <<
228 throw ExceptionMessage(WarningException, _("InsetCommand Error: "),
229 _("Incompatible command name."));
233 info_ = findInfo(insetCode_, cmdName_);
237 void InsetCommandParams::read(Lexer & lex)
241 string const insetType = lex.getString();
242 InsetCode const code = insetCode(insetType);
243 if (code != insetCode_) {
244 lex.printError("InsetCommandParams: Attempt to change type of inset.");
245 throw ExceptionMessage(WarningException, _("InsetCommandParams Error: "),
246 _("Attempt to change type of parameters."));
252 string const test = lex.getString();
253 if (test != "LatexCommand") {
254 lex.printError("InsetCommandParams: No LatexCommand line found.");
255 throw ExceptionMessage(WarningException, _("InsetCommandParams error:"),
256 _("Can't find LatexCommand line."));
260 cmdName_ = lex.getString();
261 if (!isCompatibleCommand(insetCode_, cmdName_)){
262 lex.printError("InsetCommandParams: Incompatible command name " + cmdName_ + ".");
263 throw ExceptionMessage(WarningException, _("InsetCommandParams Error: "),
264 _("Incompatible command name."));
267 info_ = findInfo(insetCode_, cmdName_);
272 token = lex.getString();
273 if (token == "\\end_inset")
275 if (token == "preview") {
277 preview_ = lex.getBool();
280 if (info_.hasParam(token)) {
282 params_[token] = lex.getDocString();
284 lex.printError("Unknown parameter name `$$Token' for command " + cmdName_);
285 throw ExceptionMessage(WarningException,
286 _("InsetCommandParams: ") + from_ascii(cmdName_),
287 _("Unknown parameter name: ") + from_utf8(token));
290 if (token != "\\end_inset") {
291 lex.printError("Missing \\end_inset at this point. "
293 throw ExceptionMessage(WarningException,
294 _("Missing \\end_inset at this point."),
300 void InsetCommandParams::write(ostream & os) const
302 os << "CommandInset " << insetType() << '\n';
303 os << "LatexCommand " << cmdName_ << '\n';
305 os << "preview true\n";
306 ParamInfo::const_iterator it = info_.begin();
307 ParamInfo::const_iterator end = info_.end();
308 for (; it != end; ++it) {
309 std::string const & name = it->name();
310 docstring const & data = (*this)[name];
314 << Lexer::quoteString(to_utf8(data))
321 docstring const InsetCommandParams::getCommand() const
323 docstring s = '\\' + from_ascii(cmdName_);
325 ParamInfo::const_iterator it = info_.begin();
326 ParamInfo::const_iterator end = info_.end();
327 for (; it != end; ++it) {
328 std::string const & name = it->name();
329 docstring const & data = (*this)[name];
330 if (!it->isOptional()) {
331 s += '{' + data + '}';
336 s += '[' + data + ']';
340 // This param is therefore optional but empty.
341 // But we need to write it anyway if nonempty
342 // optional parameters follow before the next
343 // required parameter.
344 ParamInfo::const_iterator it2 = it;
345 for (++it2; it2 != end; ++it2) {
346 if (!it2->isOptional())
348 std::string const & name2 = it2->name();
349 docstring const & data2 = (*this)[name2];
350 if (!data2.empty()) {
358 // Make sure that following stuff does not change the
366 //predicate for what follows
367 bool paramIsNonOptional(ParamInfo::ParamData pi)
369 return !pi.isOptional();
373 docstring const InsetCommandParams::getFirstNonOptParam() const
375 ParamInfo::const_iterator it =
376 find_if(info_.begin(), info_.end(), paramIsNonOptional);
377 if (it == info_.end())
379 return (*this)[it->name()];
383 docstring const & InsetCommandParams::operator[](string const & name) const
385 static const docstring dummy; //so we don't return a ref to temporary
386 if (!info_.hasParam(name))
388 ParamMap::const_iterator data = params_.find(name);
389 if (data == params_.end() || data->second.empty())
395 docstring & InsetCommandParams::operator[](string const & name)
397 if (!info_.hasParam(name))
399 return params_[name];
403 void InsetCommandParams::clear()
409 bool operator==(InsetCommandParams const & o1,
410 InsetCommandParams const & o2)
412 return o1.insetCode_ == o2.insetCode_ &&
413 o1.cmdName_ == o2.cmdName_ &&
414 o1.info_ == o2.info_ &&
415 o1.params_ == o2.params_ &&
416 o1.preview_ == o2.preview_;
420 bool operator!=(InsetCommandParams const & o1,
421 InsetCommandParams const & o2)