X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetCommandParams.cpp;h=90fe6cca8ad813cd38ac067f29b1e13ee25610ff;hb=06254d11dfdf670fab3548dc2a2674e7a261262c;hp=b27821bcb05b9c7eaa4024402e0607f13c9165f7;hpb=a46d7ee8570f3383ab4642eff7b5353a85286f33;p=lyx.git diff --git a/src/insets/InsetCommandParams.cpp b/src/insets/InsetCommandParams.cpp index b27821bcb0..90fe6cca8a 100644 --- a/src/insets/InsetCommandParams.cpp +++ b/src/insets/InsetCommandParams.cpp @@ -5,6 +5,7 @@ * * \author Angus Leeming * \author Georg Baum + * \author Richard Heck * * Full author contact details are available in file CREDITS. */ @@ -13,27 +14,34 @@ #include "InsetCommandParams.h" -#include "debug.h" -#include "gettext.h" +#include "InsetBibitem.h" +#include "InsetBibtex.h" +#include "InsetCitation.h" +#include "InsetFloatList.h" +#include "InsetHFill.h" +#include "InsetHyperlink.h" +#include "InsetInclude.h" +#include "InsetIndex.h" +#include "InsetLabel.h" +#include "InsetNomencl.h" +#include "InsetRef.h" +#include "InsetTOC.h" + +#include "support/debug.h" +#include "support/gettext.h" #include "Lexer.h" #include "support/ExceptionMessage.h" #include "support/lstrings.h" +#include "support/docstream.h" #include +using namespace std; +using namespace lyx::support; namespace lyx { -using support::findToken; - -using std::string; -using std::endl; -using std::ostream; - -using support::ExceptionMessage; -using support::WarningException; - InsetCommandParams::InsetCommandParams(InsetCode code) : insetCode_(code), preview_(false) @@ -55,101 +63,36 @@ InsetCommandParams::InsetCommandParams(InsetCode code, } -//FIXME This should go into the Insets themselves...so they will tell -//us what parameters they want. -//Should this just vanish in favor of the two arg version, or is there -//a reason to use it in some cases? What should happen in the single -//arg case, then? Maybe use the default? or leave that up to the inset? -InsetCommandParams::CommandInfo const * - InsetCommandParams::findInfo(InsetCode code) +CommandInfo const * InsetCommandParams::findInfo( + InsetCode code, string const & cmdName) { - // No parameter may be named "preview", because that is a required - // flag for all commands. - switch (code) { - case BIBITEM_CODE: { - static const char * const paramnames[] = {"label", "key", ""}; - static const bool isoptional[] = {true, false}; - static const CommandInfo info = {2, paramnames, isoptional}; - return &info; - } - case BIBTEX_CODE: { - static const char * const paramnames[] = - {"options", "btprint", "bibfiles", ""}; - static const bool isoptional[] = {true, true, false}; - static const CommandInfo info = {3, paramnames, isoptional}; - return &info; - } - case CITE_CODE: { - // standard cite does only take one argument if jurabib is - // not used, but jurabib extends this to two arguments, so - // we have to allow both here. InsetCitation takes care that - // LaTeX output is nevertheless correct. - static const char * const paramnames[] = - {"after", "before", "key", ""}; - static const bool isoptional[] = {true, true, false}; - static const CommandInfo info = {3, paramnames, isoptional}; - return &info; - } - case FLOAT_LIST_CODE: { - static const char * const paramnames[] = {"type", ""}; - static const bool isoptional[] = {false}; - static const CommandInfo info = {1, paramnames, isoptional}; - return &info; - } - case HFILL_CODE: { - static const char * const paramnames[] = {""}; - static const CommandInfo info = {0, paramnames, 0}; - return &info; - } - case HYPERLINK_CODE: { - static const char * const paramnames[] = - {"name", "target", ""}; - static const bool isoptional[] = {true, false}; - static const CommandInfo info = {2, paramnames, isoptional}; - return &info; - } - case INCLUDE_CODE: { - //This is only correct for the case of listings, but it'll do for now. - //In the other cases, this second parameter should just be empty. - static const char * const paramnames[] = {"filename", "lstparams", ""}; - static const bool isoptional[] = {false, true}; - static const CommandInfo info = {2, paramnames, isoptional}; - return &info; - } - case INDEX_CODE: + case BIBITEM_CODE: + return InsetBibitem::findInfo(cmdName); + case BIBTEX_CODE: + return InsetBibtex::findInfo(cmdName); + case CITE_CODE: + return InsetCitation::findInfo(cmdName); + case FLOAT_LIST_CODE: + return InsetFloatList::findInfo(cmdName); + case HFILL_CODE: + return InsetHFill::findInfo(cmdName); + case HYPERLINK_CODE: + return InsetHyperlink::findInfo(cmdName); + case INCLUDE_CODE: + return InsetInclude::findInfo(cmdName); case INDEX_PRINT_CODE: - case LABEL_CODE: { - static const char * const paramnames[] = {"name", ""}; - static const bool isoptional[] = {false}; - static const CommandInfo info = {1, paramnames, isoptional}; - return &info; - } - case NOMENCL_CODE: { - static const char * const paramnames[] = {"prefix", "symbol", "description", ""}; - static const bool isoptional[] = {true, false, false}; - static const CommandInfo info = {3, paramnames, isoptional}; - return &info; - } - case NOMENCL_PRINT_CODE: { - static const char * const paramnames[] = {"labelwidth", ""}; - static const bool isoptional[] = {true}; - static const CommandInfo info = {1, paramnames, isoptional}; - return &info; - } - case REF_CODE: { - static const char * const paramnames[] = - {"name", "reference", ""}; - static const bool isoptional[] = {true, false}; - static const CommandInfo info = {2, paramnames, isoptional}; - return &info; - } - case TOC_CODE: { - static const char * const paramnames[] = {"type", ""}; - static const bool isoptional[] = {false}; - static const CommandInfo info = {1, paramnames, isoptional}; - return &info; - } + return InsetPrintIndex::findInfo(cmdName); + case LABEL_CODE: + return InsetLabel::findInfo(cmdName); + case NOMENCL_CODE: + return InsetNomencl::findInfo(cmdName); + case NOMENCL_PRINT_CODE: + return InsetPrintNomencl::findInfo(cmdName); + case REF_CODE: + return InsetRef::findInfo(cmdName); + case TOC_CODE: + return InsetTOC::findInfo(cmdName); default: BOOST_ASSERT(false); } @@ -157,61 +100,92 @@ InsetCommandParams::CommandInfo const * } -//FIXME Will eventually call a static method, etc. -InsetCommandParams::CommandInfo const * - InsetCommandParams::findInfo(InsetCode code, - std::string const &/* cmdName*/) -{ - return findInfo(code); +string InsetCommandParams::getDefaultCmd(InsetCode code) { + switch (code) { + case BIBITEM_CODE: + return InsetBibitem::defaultCommand(); + case BIBTEX_CODE: + return InsetBibtex::defaultCommand(); + case CITE_CODE: + return InsetCitation::defaultCommand(); + case FLOAT_LIST_CODE: + return InsetFloatList::defaultCommand(); + case HFILL_CODE: + return InsetHFill::defaultCommand(); + case HYPERLINK_CODE: + return InsetHyperlink::defaultCommand(); + case INCLUDE_CODE: + return InsetInclude::defaultCommand(); + case INDEX_PRINT_CODE: + return InsetPrintIndex::defaultCommand(); + case LABEL_CODE: + return InsetLabel::defaultCommand(); + case NOMENCL_CODE: + return InsetNomencl::defaultCommand(); + case NOMENCL_PRINT_CODE: + return InsetPrintNomencl::defaultCommand(); + case REF_CODE: + return InsetRef::defaultCommand(); + case TOC_CODE: + return InsetTOC::defaultCommand(); + default: + BOOST_ASSERT(false); + } + return string(); //silence the warning } -//FIXME Should call InsetBibitem::getDefaultCmd(), eg -std::string InsetCommandParams::getDefaultCmd(InsetCode code) { +bool InsetCommandParams::isCompatibleCommand( + InsetCode code, string const & s) +{ switch (code) { case BIBITEM_CODE: - return "bibitem"; + return InsetBibitem::isCompatibleCommand(s); case BIBTEX_CODE: - return "bibtex"; //this is an unused dummy + return InsetBibtex::isCompatibleCommand(s); case CITE_CODE: - return "cite"; + return InsetCitation::isCompatibleCommand(s); case FLOAT_LIST_CODE: - return "listoftables"; + return InsetFloatList::isCompatibleCommand(s); case HFILL_CODE: - return "hfill"; + return InsetHFill::isCompatibleCommand(s); case HYPERLINK_CODE: - return "href"; + return InsetHyperlink::isCompatibleCommand(s); case INCLUDE_CODE: - return "include"; - case INDEX_CODE: - return "index"; + return InsetInclude::isCompatibleCommand(s); case INDEX_PRINT_CODE: - return "printindex"; + return InsetPrintIndex::isCompatibleCommand(s); case LABEL_CODE: - return "label"; + return InsetLabel::isCompatibleCommand(s); case NOMENCL_CODE: - return "nomenclature"; + return InsetNomencl::isCompatibleCommand(s); case NOMENCL_PRINT_CODE: - return "printnomenclature"; + return InsetPrintNomencl::isCompatibleCommand(s); case REF_CODE: - return "ref"; + return InsetRef::isCompatibleCommand(s); case TOC_CODE: - return "tableofcontents"; + return InsetTOC::isCompatibleCommand(s); default: BOOST_ASSERT(false); } - return ""; + return false; //silence the warning } void InsetCommandParams::setCmdName(string const & name) { - //FIXME Check command compatibility + if (!isCompatibleCommand(insetCode_, cmdName_)){ + LYXERR0("InsetCommand: Incompatible command name " << + name << "."); + throw ExceptionMessage(WarningException, _("InsetCommand Error: "), + from_utf8("Incompatible command name.")); + } + cmdName_ = name; CommandInfo const * const info = findInfo(insetCode_, cmdName_); if (!info) { - lyxerr << "Command '" << name << "' is not compatible with a '" << - insetType() << "' inset." << std::endl; + LYXERR0("Command '" << name << "' is not compatible with a '" << + insetType() << "' inset."); return; } ParamVector params(info->n); @@ -222,84 +196,12 @@ void InsetCommandParams::setCmdName(string const & name) params[j] = params_[i]; } info_ = info; - std::swap(params, params_); -} - - -void InsetCommandParams::scanCommand(string const & cmd) -{ - string tcmdname, toptions, tsecoptions, tcontents; - - if (cmd.empty()) return; - - enum { WS, CMDNAME, OPTION, SECOPTION, CONTENT } state = WS; - - // Used to handle things like \command[foo[bar]]{foo{bar}} - int nestdepth = 0; - - for (string::size_type i = 0; i < cmd.length(); ++i) { - char const c = cmd[i]; - if ((state == CMDNAME && c == ' ') || - (state == CMDNAME && c == '[') || - (state == CMDNAME && c == '{')) { - state = WS; - } - if ((state == OPTION && c == ']') || - (state == SECOPTION && c == ']') || - (state == CONTENT && c == '}')) { - if (nestdepth == 0) { - state = WS; - } else { - --nestdepth; - } - } - if ((state == OPTION && c == '[') || - (state == SECOPTION && c == '[') || - (state == CONTENT && c == '{')) { - ++nestdepth; - } - switch (state) { - case CMDNAME: tcmdname += c; break; - case OPTION: toptions += c; break; - case SECOPTION: tsecoptions += c; break; - case CONTENT: tcontents += c; break; - case WS: { - char const b = i? cmd[i-1]: 0; - if (c == '\\') { - state = CMDNAME; - } else if (c == '[' && b != ']') { - state = OPTION; - nestdepth = 0; // Just to be sure - } else if (c == '[' && b == ']') { - state = SECOPTION; - nestdepth = 0; // Just to be sure - } else if (c == '{') { - state = CONTENT; - nestdepth = 0; // Just to be sure - } - break; - } - } - } - - // Don't mess with this. - if (!tcmdname.empty()) setCmdName(tcmdname); - if (!toptions.empty()) setOptions(toptions); - if (!tsecoptions.empty()) setSecOptions(tsecoptions); - if (!tcontents.empty()) setContents(tcontents); - - LYXERR(Debug::PARSER) << "Command <" << cmd - << "> == <" << to_utf8(getCommand()) - << "> == <" << getCmdName() - << '|' << getContents() - << '|' << getOptions() - << '|' << getSecOptions() << '>' << endl; + swap(params, params_); } void InsetCommandParams::read(Lexer & lex) { - //FIXME if (lex.isOK()) { lex.next(); string const insetType = lex.getString(); @@ -322,12 +224,12 @@ void InsetCommandParams::read(Lexer & lex) } lex.next(); cmdName_ = lex.getString(); - //FIXME - //check that this command is ok with the inset... - //so that'll be some kind of static call, depending - //upon what insetType_ is. - //it's possible that should go into InsetCommand.cpp, - //or maybe it's a standalone function. + if (!isCompatibleCommand(insetCode_, cmdName_)){ + lex.printError("InsetCommand: Incompatible command name " + cmdName_ + "."); + throw ExceptionMessage(WarningException, _("InsetCommand Error: "), + from_utf8("Incompatible command name.")); + } + info_ = findInfo(insetCode_, cmdName_); if (!info_) { lex.printError("InsetCommand: Unknown inset name `$$Token'"); @@ -341,7 +243,6 @@ void InsetCommandParams::read(Lexer & lex) token = lex.getString(); if (token == "\\end_inset") break; - // FIXME Why is preview_ read but not written? if (token == "preview") { lex.next(); preview_ = lex.getBool(); @@ -372,6 +273,8 @@ 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()) // FIXME UNICODE @@ -417,82 +320,13 @@ docstring const InsetCommandParams::getCommand() const } -std::string const InsetCommandParams::getOptions() const -{ - for (size_t i = 0; i < info_->n; ++i) - if (info_->optional[i]) - return to_utf8(params_[i]); - lyxerr << "Programming error: get nonexisting option in " - << insetType() << " inset." << endl; - return string(); -} - - -std::string const InsetCommandParams::getSecOptions() const -{ - bool first = true; - for (size_t i = 0; i < info_->n; ++i) - if (info_->optional[i]) { - if (first) - first = false; - else - return to_utf8(params_[i]); - } - // Happens in InsetCitation - lyxerr << "Programming error: get nonexisting second option in " - << insetType() << " inset." << endl; - return string(); -} - - -std::string const InsetCommandParams::getContents() const +docstring const InsetCommandParams::getFirstNonOptParam() const { for (size_t i = 0; i < info_->n; ++i) if (!info_->optional[i]) - return to_utf8(params_[i]); - BOOST_ASSERT(false); - return string(); -} - - -void InsetCommandParams::setOptions(std::string const & o) -{ - for (size_t i = 0; i < info_->n; ++i) - if (info_->optional[i]) { - params_[i] = from_utf8(o); - return; - } - lyxerr << "Programming error: set nonexisting option in " - << insetType() << " inset." << endl; -} - - -void InsetCommandParams::setSecOptions(std::string const & s) -{ - bool first = true; - for (size_t i = 0; i < info_->n; ++i) - if (info_->optional[i]) { - if (first) - first = false; - else { - params_[i] = from_utf8(s); - return; - } - } - // Happens in InsetCitation - lyxerr << "Programming error: set nonexisting second option in " - << insetType() << " inset." << endl; -} - - -void InsetCommandParams::setContents(std::string const & c) -{ - for (size_t i = 0; i < info_->n; ++i) - if (!info_->optional[i]) { - params_[i] = from_utf8(c); - return; - } + return params_[i]; BOOST_ASSERT(false); + return docstring(); }