X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetCommandParams.cpp;h=f1804a29d9cefb8762b56064b5b86a08d86c0944;hb=0362c6aae73c293d1c20277c12d362acfe0b2ef6;hp=39b066bace83c53fdb2ae64e9d10e4526b2266f9;hpb=9d0ea8aeff32833a90b3fe64df0c5518a9e241be;p=lyx.git diff --git a/src/insets/InsetCommandParams.cpp b/src/insets/InsetCommandParams.cpp index 39b066bace..f1804a29d9 100644 --- a/src/insets/InsetCommandParams.cpp +++ b/src/insets/InsetCommandParams.cpp @@ -27,32 +27,78 @@ #include "InsetRef.h" #include "InsetTOC.h" -#include "support/debug.h" -#include "support/gettext.h" #include "Lexer.h" +#include "support/debug.h" #include "support/ExceptionMessage.h" +#include "support/gettext.h" #include "support/lstrings.h" #include "support/docstream.h" #include -using std::string; - +using namespace std; +using namespace lyx::support; namespace lyx { -using support::findToken; -using support::ExceptionMessage; -using support::WarningException; +ParamInfo::ParamData::ParamData(std::string const & s, bool b) : + name_(s), optional_(b) +{} + + +bool ParamInfo::ParamData::operator==(ParamInfo::ParamData const & rhs) const +{ + return name() == rhs.name() && isOptional() == rhs.isOptional(); +} + + +bool ParamInfo::hasParam(std::string const & name) const +{ + const_iterator it = begin(); + for (; it != end(); ++it) { + if (it->name() == name) + return true; + } + return false; +} + + +void ParamInfo::add(std::string const & name, bool opt) +{ + info_.push_back(ParamData(name, opt)); +} + + +bool ParamInfo::operator==(ParamInfo const & rhs) const +{ + // the idea here is to check each ParamData for equality + const_iterator itL = begin(); + const_iterator itR = rhs.begin(); + const_iterator endL = end(); + const_iterator endR = rhs.end(); + while (true) { + // if they both end together, return true + if (itL == endL && itR == endR) + return true; + // but if one ends before the other, return false + if (itL == endL || itR == endR) + return false; + //check this one for equality + if (*itL != *itR) + return false; + // equal, so check the next one + ++itL; + ++itR; + } +} + InsetCommandParams::InsetCommandParams(InsetCode code) : insetCode_(code), preview_(false) { cmdName_ = getDefaultCmd(code); info_ = findInfo(code, cmdName_); - BOOST_ASSERT(info_); - params_.resize(info_->n); } @@ -61,13 +107,11 @@ InsetCommandParams::InsetCommandParams(InsetCode code, : insetCode_(code), cmdName_(cmdName), preview_(false) { info_ = findInfo(code, cmdName); - BOOST_ASSERT(info_); - params_.resize(info_->n); } -CommandInfo const * InsetCommandParams::findInfo( - InsetCode code, std::string const & cmdName) +ParamInfo const & InsetCommandParams::findInfo( + InsetCode code, string const & cmdName) { switch (code) { case BIBITEM_CODE: @@ -99,11 +143,12 @@ CommandInfo const * InsetCommandParams::findInfo( default: BOOST_ASSERT(false); } - return 0; + static const ParamInfo pi; + return pi; // to silence the warning } -std::string InsetCommandParams::getDefaultCmd(InsetCode code) { +string InsetCommandParams::getDefaultCmd(InsetCode code) { switch (code) { case BIBITEM_CODE: return InsetBibitem::defaultCommand(); @@ -134,12 +179,12 @@ std::string InsetCommandParams::getDefaultCmd(InsetCode code) { default: BOOST_ASSERT(false); } - return string(); //silence the warning + return string(); // silence the warning } bool InsetCommandParams::isCompatibleCommand( - InsetCode code, std::string const & s) + InsetCode code, string const & s) { switch (code) { case BIBITEM_CODE: @@ -171,7 +216,7 @@ bool InsetCommandParams::isCompatibleCommand( default: BOOST_ASSERT(false); } - return false; //silence the warning + return false; // silence the warning } @@ -181,25 +226,11 @@ void InsetCommandParams::setCmdName(string const & name) LYXERR0("InsetCommand: Incompatible command name " << name << "."); throw ExceptionMessage(WarningException, _("InsetCommand Error: "), - from_utf8("Incompatible command name.")); + _("Incompatible command name.")); } cmdName_ = name; - CommandInfo const * const info = findInfo(insetCode_, cmdName_); - if (!info) { - LYXERR0("Command '" << name << "' is not compatible with a '" << - insetType() << "' inset."); - return; - } - ParamVector params(info->n); - // Overtake parameters with the same name - for (size_t i = 0; i < info_->n; ++i) { - int j = findToken(info->paramnames, info_->paramnames[i]); - if (j >= 0) - params[j] = params_[i]; - } - info_ = info; - std::swap(params, params_); + info_ = findInfo(insetCode_, cmdName_); } @@ -210,9 +241,9 @@ void InsetCommandParams::read(Lexer & lex) string const insetType = lex.getString(); InsetCode const code = insetCode(insetType); if (code != insetCode_) { - lex.printError("InsetCommand: Attempt to change type of parameters."); - throw ExceptionMessage(WarningException, _("InsetCommand Error: "), - from_utf8("Attempt to change type of parameters.")); + lex.printError("InsetCommandParams: Attempt to change type of inset."); + throw ExceptionMessage(WarningException, _("InsetCommandParams Error: "), + _("Attempt to change type of parameters.")); } } @@ -220,25 +251,20 @@ void InsetCommandParams::read(Lexer & lex) lex.next(); string const test = lex.getString(); if (test != "LatexCommand") { - lex.printError("InsetCommand: no LatexCommand line found."); - throw ExceptionMessage(WarningException, _("InsetCommand error:"), - from_utf8("Can't find LatexCommand line.")); + lex.printError("InsetCommandParams: No LatexCommand line found."); + throw ExceptionMessage(WarningException, _("InsetCommandParams error:"), + _("Can't find LatexCommand line.")); } } lex.next(); cmdName_ = lex.getString(); if (!isCompatibleCommand(insetCode_, cmdName_)){ - lex.printError("InsetCommand: Incompatible command name " + cmdName_ + "."); - throw ExceptionMessage(WarningException, _("InsetCommand Error: "), - from_utf8("Incompatible command name.")); + lex.printError("InsetCommandParams: Incompatible command name " + cmdName_ + "."); + throw ExceptionMessage(WarningException, _("InsetCommandParams Error: "), + _("Incompatible command name.")); } info_ = findInfo(insetCode_, cmdName_); - if (!info_) { - lex.printError("InsetCommand: Unknown inset name `$$Token'"); - throw ExceptionMessage(WarningException, - _("Unknown inset name: "), from_utf8(insetType())); - } string token; while (lex.isOK()) { @@ -251,14 +277,13 @@ void InsetCommandParams::read(Lexer & lex) preview_ = lex.getBool(); continue; } - int const i = findToken(info_->paramnames, token); - if (i >= 0) { + if (info_.hasParam(token)) { lex.next(true); - params_[i] = lex.getDocString(); + params_[token] = lex.getDocString(); } else { lex.printError("Unknown parameter name `$$Token' for command " + cmdName_); throw ExceptionMessage(WarningException, - _("Inset Command: ") + from_ascii(cmdName_), + _("InsetCommandParams: ") + from_ascii(cmdName_), _("Unknown parameter name: ") + from_utf8(token)); } } @@ -272,18 +297,24 @@ void InsetCommandParams::read(Lexer & lex) } -void InsetCommandParams::write(std::ostream & os) const +void InsetCommandParams::write(ostream & os) const { os << "CommandInset " << insetType() << '\n'; os << "LatexCommand " << cmdName_ << '\n'; if (preview_) os << "preview true\n"; - for (size_t i = 0; i < info_->n; ++i) - if (!params_[i].empty()) + ParamInfo::const_iterator it = info_.begin(); + ParamInfo::const_iterator end = info_.end(); + for (; it != end; ++it) { + std::string const & name = it->name(); + docstring const & data = (*this)[name]; + if (!data.empty()) { // FIXME UNICODE - os << info_->paramnames[i] << ' ' - << Lexer::quoteString(to_utf8(params_[i])) + os << name << ' ' + << Lexer::quoteString(to_utf8(data)) << '\n'; + } + } } @@ -291,28 +322,36 @@ docstring const InsetCommandParams::getCommand() const { docstring s = '\\' + from_ascii(cmdName_); bool noparam = true; - for (size_t i = 0; i < info_->n; ++i) { - if (info_->optional[i]) { - if (params_[i].empty()) { - // We need to write this parameter even if - // it is empty if nonempty optional parameters - // follow before the next required parameter. - for (size_t j = i + 1; j < info_->n; ++j) { - if (!info_->optional[j]) - break; - if (!params_[j].empty()) { - s += "[]"; - noparam = false; - break; - } - } - } else { - s += '[' + params_[i] + ']'; + ParamInfo::const_iterator it = info_.begin(); + ParamInfo::const_iterator end = info_.end(); + for (; it != end; ++it) { + std::string const & name = it->name(); + docstring const & data = (*this)[name]; + if (!it->isOptional()) { + s += '{' + data + '}'; + noparam = false; + continue; + } + if (!data.empty()) { + s += '[' + data + ']'; + noparam = false; + continue; + } + // This param is therefore optional but empty. + // But we need to write it anyway if nonempty + // optional parameters follow before the next + // required parameter. + ParamInfo::const_iterator it2 = it; + for (++it2; it2 != end; ++it2) { + if (!it2->isOptional()) + break; + std::string const & name2 = it2->name(); + docstring const & data2 = (*this)[name2]; + if (!data2.empty()) { + s += "[]"; noparam = false; + break; } - } else { - s += '{' + params_[i] + '}'; - noparam = false; } } if (noparam) @@ -323,36 +362,47 @@ docstring const InsetCommandParams::getCommand() const } +namespace { + //predicate for what follows + bool paramIsNonOptional(ParamInfo::ParamData pi) + { + return !pi.isOptional(); + } +} + docstring const InsetCommandParams::getFirstNonOptParam() const { - for (size_t i = 0; i < info_->n; ++i) - if (!info_->optional[i]) - return params_[i]; - BOOST_ASSERT(false); - return docstring(); + ParamInfo::const_iterator it = + find_if(info_.begin(), info_.end(), paramIsNonOptional); + if (it == info_.end()) + BOOST_ASSERT(false); + return (*this)[it->name()]; } docstring const & InsetCommandParams::operator[](string const & name) const { - int const i = findToken(info_->paramnames, name); - BOOST_ASSERT(i >= 0); - return params_[i]; + static const docstring dummy; //so we don't return a ref to temporary + if (!info_.hasParam(name)) + BOOST_ASSERT(false); + ParamMap::const_iterator data = params_.find(name); + if (data == params_.end() || data->second.empty()) + return dummy; + return data->second; } docstring & InsetCommandParams::operator[](string const & name) { - int const i = findToken(info_->paramnames, name); - BOOST_ASSERT(i >= 0); - return params_[i]; + if (!info_.hasParam(name)) + BOOST_ASSERT(false); + return params_[name]; } void InsetCommandParams::clear() { - for (size_t i = 0; i < info_->n; ++i) - params_[i].clear(); + params_.clear(); }