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
9 * Full author contact details are available in file CREDITS.
14 #include "InsetCommandParams.h"
20 #include "support/ExceptionMessage.h"
21 #include "support/lstrings.h"
23 #include <boost/assert.hpp>
28 using support::findToken;
34 using support::ExceptionMessage;
35 using support::WarningException;
38 InsetCommandParams::InsetCommandParams(InsetCode code)
39 : insetCode_(code), preview_(false)
41 cmdName_ = getDefaultCmd(code);
42 info_ = findInfo(code, cmdName_);
44 params_.resize(info_->n);
48 InsetCommandParams::InsetCommandParams(InsetCode code,
49 string const & cmdName)
50 : insetCode_(code), cmdName_(cmdName), preview_(false)
52 info_ = findInfo(code, cmdName);
54 params_.resize(info_->n);
58 //FIXME This should go into the Insets themselves...so they will tell
59 //us what parameters they want.
60 //Should this just vanish in favor of the two arg version, or is there
61 //a reason to use it in some cases? What should happen in the single
62 //arg case, then? Maybe use the default? or leave that up to the inset?
63 InsetCommandParams::CommandInfo const *
64 InsetCommandParams::findInfo(InsetCode code)
66 // No parameter may be named "preview", because that is a required
67 // flag for all commands.
71 static const char * const paramnames[] = {"label", "key", ""};
72 static const bool isoptional[] = {true, false};
73 static const CommandInfo info = {2, paramnames, isoptional};
77 static const char * const paramnames[] =
78 {"options", "btprint", "bibfiles", ""};
79 static const bool isoptional[] = {true, true, false};
80 static const CommandInfo info = {3, paramnames, isoptional};
84 // standard cite does only take one argument if jurabib is
85 // not used, but jurabib extends this to two arguments, so
86 // we have to allow both here. InsetCitation takes care that
87 // LaTeX output is nevertheless correct.
88 static const char * const paramnames[] =
89 {"after", "before", "key", ""};
90 static const bool isoptional[] = {true, true, false};
91 static const CommandInfo info = {3, paramnames, isoptional};
94 case FLOAT_LIST_CODE: {
95 static const char * const paramnames[] = {"type", ""};
96 static const bool isoptional[] = {false};
97 static const CommandInfo info = {1, paramnames, isoptional};
101 static const char * const paramnames[] = {""};
102 static const CommandInfo info = {0, paramnames, 0};
105 case HYPERLINK_CODE: {
106 static const char * const paramnames[] =
107 {"name", "target", ""};
108 static const bool isoptional[] = {true, false};
109 static const CommandInfo info = {2, paramnames, isoptional};
113 //This is only correct for the case of listings, but it'll do for now.
114 //In the other cases, this second parameter should just be empty.
115 static const char * const paramnames[] = {"filename", "lstparams", ""};
116 static const bool isoptional[] = {false, true};
117 static const CommandInfo info = {2, paramnames, isoptional};
121 case INDEX_PRINT_CODE:
123 static const char * const paramnames[] = {"name", ""};
124 static const bool isoptional[] = {false};
125 static const CommandInfo info = {1, paramnames, isoptional};
129 static const char * const paramnames[] = {"prefix", "symbol", "description", ""};
130 static const bool isoptional[] = {true, false, false};
131 static const CommandInfo info = {3, paramnames, isoptional};
134 case NOMENCL_PRINT_CODE: {
135 static const char * const paramnames[] = {"labelwidth", ""};
136 static const bool isoptional[] = {true};
137 static const CommandInfo info = {1, paramnames, isoptional};
141 static const char * const paramnames[] =
142 {"name", "reference", ""};
143 static const bool isoptional[] = {true, false};
144 static const CommandInfo info = {2, paramnames, isoptional};
148 static const char * const paramnames[] = {"type", ""};
149 static const bool isoptional[] = {false};
150 static const CommandInfo info = {1, paramnames, isoptional};
160 //FIXME Will eventually call a static method, etc.
161 InsetCommandParams::CommandInfo const *
162 InsetCommandParams::findInfo(InsetCode code,
163 std::string const &/* cmdName*/)
165 return findInfo(code);
169 //FIXME Should call InsetBibitem::getDefaultCmd(), eg
170 std::string InsetCommandParams::getDefaultCmd(InsetCode code) {
175 return "bibtex"; //this is an unused dummy
178 case FLOAT_LIST_CODE:
179 return "listoftables";
188 case INDEX_PRINT_CODE:
193 return "nomenclature";
194 case NOMENCL_PRINT_CODE:
195 return "printnomenclature";
199 return "tableofcontents";
207 void InsetCommandParams::setCmdName(string const & name)
209 //FIXME Check command compatibility
211 CommandInfo const * const info = findInfo(insetCode_, cmdName_);
213 lyxerr << "Command '" << name << "' is not compatible with a '" <<
214 insetType() << "' inset." << std::endl;
217 ParamVector params(info->n);
218 // Overtake parameters with the same name
219 for (size_t i = 0; i < info_->n; ++i) {
220 int j = findToken(info->paramnames, info_->paramnames[i]);
222 params[j] = params_[i];
225 std::swap(params, params_);
229 void InsetCommandParams::read(Lexer & lex)
233 string const insetType = lex.getString();
234 InsetCode const code = insetCode(insetType);
235 if (code != insetCode_) {
236 lex.printError("InsetCommand: Attempt to change type of parameters.");
237 throw ExceptionMessage(WarningException, _("InsetCommand Error: "),
238 from_utf8("Attempt to change type of parameters."));
244 string const test = lex.getString();
245 if (test != "LatexCommand") {
246 lex.printError("InsetCommand: no LatexCommand line found.");
247 throw ExceptionMessage(WarningException, _("InsetCommand error:"),
248 from_utf8("Can't find LatexCommand line."));
252 cmdName_ = lex.getString();
254 //check that this command is ok with the inset...
255 //so that'll be some kind of static call, depending
256 //upon what insetType_ is.
257 //it's possible that should go into InsetCommand.cpp,
258 //or maybe it's a standalone function.
259 info_ = findInfo(insetCode_, cmdName_);
261 lex.printError("InsetCommand: Unknown inset name `$$Token'");
262 throw ExceptionMessage(WarningException,
263 _("Unknown inset name: "), from_utf8(insetType()));
269 token = lex.getString();
270 if (token == "\\end_inset")
272 if (token == "preview") {
274 preview_ = lex.getBool();
277 int const i = findToken(info_->paramnames, token);
280 params_[i] = lex.getDocString();
282 lex.printError("Unknown parameter name `$$Token' for command " + cmdName_);
283 throw ExceptionMessage(WarningException,
284 _("Inset Command: ") + from_ascii(cmdName_),
285 _("Unknown parameter name: ") + from_utf8(token));
288 if (token != "\\end_inset") {
289 lex.printError("Missing \\end_inset at this point. "
291 throw ExceptionMessage(WarningException,
292 _("Missing \\end_inset at this point."),
298 void InsetCommandParams::write(ostream & os) const
300 os << "CommandInset " << insetType() << '\n';
301 os << "LatexCommand " << cmdName_ << '\n';
303 os << "preview true\n";
304 for (size_t i = 0; i < info_->n; ++i)
305 if (!params_[i].empty())
307 os << info_->paramnames[i] << ' '
308 << Lexer::quoteString(to_utf8(params_[i]))
313 docstring const InsetCommandParams::getCommand() const
315 docstring s = '\\' + from_ascii(cmdName_);
317 for (size_t i = 0; i < info_->n; ++i) {
318 if (info_->optional[i]) {
319 if (params_[i].empty()) {
320 // We need to write this parameter even if
321 // it is empty if nonempty optional parameters
322 // follow before the next required parameter.
323 for (size_t j = i + 1; j < info_->n; ++j) {
324 if (!info_->optional[j])
326 if (!params_[j].empty()) {
333 s += '[' + params_[i] + ']';
337 s += '{' + params_[i] + '}';
342 // Make sure that following stuff does not change the
349 docstring const InsetCommandParams::getFirstNonOptParam() const
351 for (size_t i = 0; i < info_->n; ++i)
352 if (!info_->optional[i])
359 docstring const & InsetCommandParams::operator[](string const & name) const
361 int const i = findToken(info_->paramnames, name);
362 BOOST_ASSERT(i >= 0);
367 docstring & InsetCommandParams::operator[](string const & name)
369 int const i = findToken(info_->paramnames, name);
370 BOOST_ASSERT(i >= 0);
375 void InsetCommandParams::clear()
377 for (size_t i = 0; i < info_->n; ++i)
382 bool operator==(InsetCommandParams const & o1,
383 InsetCommandParams const & o2)
385 return o1.insetCode_ == o2.insetCode_ &&
386 o1.cmdName_ == o2.cmdName_ &&
387 o1.info_ == o2.info_ &&
388 o1.params_ == o2.params_ &&
389 o1.preview_ == o2.preview_;
393 bool operator!=(InsetCommandParams const & o1,
394 InsetCommandParams const & o2)