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"
30 #include "support/debug.h"
31 #include "support/gettext.h"
34 #include "support/ExceptionMessage.h"
35 #include "support/lstrings.h"
36 #include "support/docstream.h"
38 #include <boost/assert.hpp>
41 using namespace lyx::support;
46 InsetCommandParams::InsetCommandParams(InsetCode code)
47 : insetCode_(code), preview_(false)
49 cmdName_ = getDefaultCmd(code);
50 info_ = findInfo(code, cmdName_);
52 params_.resize(info_->n);
56 InsetCommandParams::InsetCommandParams(InsetCode code,
57 string const & cmdName)
58 : insetCode_(code), cmdName_(cmdName), preview_(false)
60 info_ = findInfo(code, cmdName);
62 params_.resize(info_->n);
66 CommandInfo const * InsetCommandParams::findInfo(
67 InsetCode code, string const & cmdName)
71 return InsetBibitem::findInfo(cmdName);
73 return InsetBibtex::findInfo(cmdName);
75 return InsetCitation::findInfo(cmdName);
77 return InsetFloatList::findInfo(cmdName);
79 return InsetHFill::findInfo(cmdName);
81 return InsetHyperlink::findInfo(cmdName);
83 return InsetInclude::findInfo(cmdName);
84 case INDEX_PRINT_CODE:
85 return InsetPrintIndex::findInfo(cmdName);
87 return InsetLabel::findInfo(cmdName);
89 return InsetNomencl::findInfo(cmdName);
90 case NOMENCL_PRINT_CODE:
91 return InsetPrintNomencl::findInfo(cmdName);
93 return InsetRef::findInfo(cmdName);
95 return InsetTOC::findInfo(cmdName);
103 string InsetCommandParams::getDefaultCmd(InsetCode code) {
106 return InsetBibitem::defaultCommand();
108 return InsetBibtex::defaultCommand();
110 return InsetCitation::defaultCommand();
111 case FLOAT_LIST_CODE:
112 return InsetFloatList::defaultCommand();
114 return InsetHFill::defaultCommand();
116 return InsetHyperlink::defaultCommand();
118 return InsetInclude::defaultCommand();
119 case INDEX_PRINT_CODE:
120 return InsetPrintIndex::defaultCommand();
122 return InsetLabel::defaultCommand();
124 return InsetNomencl::defaultCommand();
125 case NOMENCL_PRINT_CODE:
126 return InsetPrintNomencl::defaultCommand();
128 return InsetRef::defaultCommand();
130 return InsetTOC::defaultCommand();
134 return string(); //silence the warning
138 bool InsetCommandParams::isCompatibleCommand(
139 InsetCode code, string const & s)
143 return InsetBibitem::isCompatibleCommand(s);
145 return InsetBibtex::isCompatibleCommand(s);
147 return InsetCitation::isCompatibleCommand(s);
148 case FLOAT_LIST_CODE:
149 return InsetFloatList::isCompatibleCommand(s);
151 return InsetHFill::isCompatibleCommand(s);
153 return InsetHyperlink::isCompatibleCommand(s);
155 return InsetInclude::isCompatibleCommand(s);
156 case INDEX_PRINT_CODE:
157 return InsetPrintIndex::isCompatibleCommand(s);
159 return InsetLabel::isCompatibleCommand(s);
161 return InsetNomencl::isCompatibleCommand(s);
162 case NOMENCL_PRINT_CODE:
163 return InsetPrintNomencl::isCompatibleCommand(s);
165 return InsetRef::isCompatibleCommand(s);
167 return InsetTOC::isCompatibleCommand(s);
171 return false; //silence the warning
175 void InsetCommandParams::setCmdName(string const & name)
177 if (!isCompatibleCommand(insetCode_, cmdName_)){
178 LYXERR0("InsetCommand: Incompatible command name " <<
180 throw ExceptionMessage(WarningException, _("InsetCommand Error: "),
181 from_utf8("Incompatible command name."));
185 CommandInfo const * const info = findInfo(insetCode_, cmdName_);
187 LYXERR0("Command '" << name << "' is not compatible with a '" <<
188 insetType() << "' inset.");
191 ParamVector params(info->n);
192 // Overtake parameters with the same name
193 for (size_t i = 0; i < info_->n; ++i) {
194 int j = findToken(info->paramnames, info_->paramnames[i]);
196 params[j] = params_[i];
199 swap(params, params_);
203 void InsetCommandParams::read(Lexer & lex)
207 string const insetType = lex.getString();
208 InsetCode const code = insetCode(insetType);
209 if (code != insetCode_) {
210 lex.printError("InsetCommand: Attempt to change type of parameters.");
211 throw ExceptionMessage(WarningException, _("InsetCommand Error: "),
212 from_utf8("Attempt to change type of parameters."));
218 string const test = lex.getString();
219 if (test != "LatexCommand") {
220 lex.printError("InsetCommand: no LatexCommand line found.");
221 throw ExceptionMessage(WarningException, _("InsetCommand error:"),
222 from_utf8("Can't find LatexCommand line."));
226 cmdName_ = lex.getString();
227 if (!isCompatibleCommand(insetCode_, cmdName_)){
228 lex.printError("InsetCommand: Incompatible command name " + cmdName_ + ".");
229 throw ExceptionMessage(WarningException, _("InsetCommand Error: "),
230 from_utf8("Incompatible command name."));
233 info_ = findInfo(insetCode_, cmdName_);
235 lex.printError("InsetCommand: Unknown inset name `$$Token'");
236 throw ExceptionMessage(WarningException,
237 _("Unknown inset name: "), from_utf8(insetType()));
243 token = lex.getString();
244 if (token == "\\end_inset")
246 if (token == "preview") {
248 preview_ = lex.getBool();
251 int const i = findToken(info_->paramnames, token);
254 params_[i] = lex.getDocString();
256 lex.printError("Unknown parameter name `$$Token' for command " + cmdName_);
257 throw ExceptionMessage(WarningException,
258 _("Inset Command: ") + from_ascii(cmdName_),
259 _("Unknown parameter name: ") + from_utf8(token));
262 if (token != "\\end_inset") {
263 lex.printError("Missing \\end_inset at this point. "
265 throw ExceptionMessage(WarningException,
266 _("Missing \\end_inset at this point."),
272 void InsetCommandParams::write(ostream & os) const
274 os << "CommandInset " << insetType() << '\n';
275 os << "LatexCommand " << cmdName_ << '\n';
277 os << "preview true\n";
278 for (size_t i = 0; i < info_->n; ++i)
279 if (!params_[i].empty())
281 os << info_->paramnames[i] << ' '
282 << Lexer::quoteString(to_utf8(params_[i]))
287 docstring const InsetCommandParams::getCommand() const
289 docstring s = '\\' + from_ascii(cmdName_);
291 for (size_t i = 0; i < info_->n; ++i) {
292 if (info_->optional[i]) {
293 if (params_[i].empty()) {
294 // We need to write this parameter even if
295 // it is empty if nonempty optional parameters
296 // follow before the next required parameter.
297 for (size_t j = i + 1; j < info_->n; ++j) {
298 if (!info_->optional[j])
300 if (!params_[j].empty()) {
307 s += '[' + params_[i] + ']';
311 s += '{' + params_[i] + '}';
316 // Make sure that following stuff does not change the
323 docstring const InsetCommandParams::getFirstNonOptParam() const
325 for (size_t i = 0; i < info_->n; ++i)
326 if (!info_->optional[i])
333 docstring const & InsetCommandParams::operator[](string const & name) const
335 int const i = findToken(info_->paramnames, name);
336 BOOST_ASSERT(i >= 0);
341 docstring & InsetCommandParams::operator[](string const & name)
343 int const i = findToken(info_->paramnames, name);
344 BOOST_ASSERT(i >= 0);
349 void InsetCommandParams::clear()
351 for (size_t i = 0; i < info_->n; ++i)
356 bool operator==(InsetCommandParams const & o1,
357 InsetCommandParams const & o2)
359 return o1.insetCode_ == o2.insetCode_ &&
360 o1.cmdName_ == o2.cmdName_ &&
361 o1.info_ == o2.info_ &&
362 o1.params_ == o2.params_ &&
363 o1.preview_ == o2.preview_;
367 bool operator!=(InsetCommandParams const & o1,
368 InsetCommandParams const & o2)