X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetListingsParams.cpp;h=f37566138f86635502bf162ccba3290dc709a0b1;hb=239b9919ffe28338d789e6dc9122228f77ab77a7;hp=6fc727975d847e7447a32a633fa9e5ed4b659091;hpb=2dca49b74a46952fc105a8e98904f6e6b63b63c1;p=lyx.git diff --git a/src/insets/InsetListingsParams.cpp b/src/insets/InsetListingsParams.cpp index 6fc727975d..f37566138f 100644 --- a/src/insets/InsetListingsParams.cpp +++ b/src/insets/InsetListingsParams.cpp @@ -9,37 +9,24 @@ */ #include +#include #include "InsetListingsParams.h" -#include "gettext.h" #include "Length.h" #include "Lexer.h" +#include "support/convert.h" +#include "support/gettext.h" #include "support/lstrings.h" #include "support/textutils.h" -#include "support/convert.h" - -#include #include -using std::map; -using std::vector; -using std::ostream; -using std::string; -using std::exception; +using namespace std; +using namespace lyx::support; -namespace lyx -{ - -using support::bformat; -using support::trim; -using support::subst; -using support::isStrInt; -using support::prefixIs; -using support::suffixIs; -using support::getVectorFromString; +namespace lyx { namespace { @@ -48,8 +35,9 @@ enum param_type { TRUEFALSE, // accept 'true' or 'false' INTEGER, // accept an integer LENGTH, // accept a latex length + SKIP, // accept a skip or a length ONEOF, // accept one of a few values - SUBSETOF, // accept a string composed of given characters + SUBSETOF // accept a string composed of given characters }; @@ -78,7 +66,7 @@ public: /// for option with value "true", "false". /// if onoff is true, /// "true": option - /// "false": + /// "false": /// "other": option="other" /// onoff is false, /// "true": option=true @@ -106,18 +94,27 @@ private: }; +char const * allowed_skips = "\\smallskipamount,\\medskipamount,\\bigskipamount"; + + docstring ListingsParam::validate(string const & par) const { bool unclosed = false; string par2 = par; // braces are allowed - if (prefixIs(par, "{") && suffixIs(par, "}")) + if (prefixIs(par, "{") && suffixIs(par, "}") && !suffixIs(par, "\\}")) par2 = par.substr(1, par.size() - 2); - else if (prefixIs(par, "{")) { - par2 = par.substr(1); - unclosed = true; + + // check for unmatched braces + int braces = 0; + for (size_t i = 0; i < par2.size(); ++i) { + if (par2[i] == '{' && (i == 0 || par2[i-1] != '\\')) + ++braces; + else if (par2[i] == '}' && (i == 0 || par2[i-1] != '\\')) + --braces; } - + unclosed = braces != 0; + switch (type_) { case ALL: @@ -128,7 +125,7 @@ docstring ListingsParam::validate(string const & par) const return _("A value is expected."); } if (unclosed) - return _("Unbalanced braces!"); + return _("Unbalanced braces!"); return docstring(); case TRUEFALSE: @@ -162,10 +159,24 @@ docstring ListingsParam::validate(string const & par) const if (!hint_.empty()) return hint_; else - return _("Please specify a latex length expression."); + return _("Please specify a LaTeX length expression."); } if (!isValidLength(par2)) - return _("Invalid latex length expression."); + return _("Invalid LaTeX length expression."); + if (unclosed) + return _("Unbalanced braces!"); + return docstring(); + + case SKIP: + if (par2.empty() && !onoff_) { + if (!hint_.empty()) + return hint_; + else + return bformat(_("Please specify a LaTeX length expression or a skip amount (%1$s)"), + from_ascii(subst(allowed_skips, ",", ", "))); + } + if (!isValidLength(par2) && tokenPos(allowed_skips, ',', par2) == -1) + return _("Not a valid LaTeX length expression or skip amount."); if (unclosed) return _("Unbalanced braces!"); return docstring(); @@ -192,14 +203,14 @@ docstring ListingsParam::validate(string const & par) const lists.push_back(v); // good, find the string - if (std::find(lists.begin(), lists.end(), par2) != lists.end()) { + if (find(lists.begin(), lists.end(), par2) != lists.end()) { if (unclosed) return _("Unbalanced braces!"); return docstring(); } // otherwise, produce a meaningful error message. string matching_names; - for (vector::iterator it = lists.begin(); + for (vector::iterator it = lists.begin(); it != lists.end(); ++it) { if (it->size() >= par2.size() && it->substr(0, par2.size()) == par2) { if (matching_names.empty()) @@ -212,6 +223,8 @@ docstring ListingsParam::validate(string const & par) const return bformat(_("Try one of %1$s."), from_utf8(info_)); else return bformat(_("I guess you mean %1$s."), from_utf8(matching_names)); + // this stifles a warning but upsets coverity + // coverity[UNREACHABLE] return docstring(); } case SUBSETOF: @@ -230,11 +243,12 @@ docstring ListingsParam::validate(string const & par) const return _("Unbalanced braces!"); return docstring(); } + return docstring(); } /// languages and language/dialect combinations -char const * allowed_languages = +char const * allowed_languages = "no language\nABAP\n[R/2 4.3]ABAP\n[R/2 5.0]ABAP\n[R/3 3.1]ABAP\n" "[R/3 4.6C]ABAP\n[R/3 6.10]ABAP\nACSL\nAda\n[2005]Ada\n[83]Ada\n" "[95]Ada\nALGOL\n[60]ALGOL\n[68]ALGOL\nAssembler\n" @@ -243,7 +257,7 @@ char const * allowed_languages = "[Sharp]C\nC++\n[ANSI]C++\n[GNU]C++\n[ISO]C++\n[Visual]C++\nCaml\n" "[light]Caml\n[Objective]Caml\nClean\nCobol\n[1974]Cobol\n[1985]Cobol\n" "[ibm]Cobol\nComal 80\ncommand.com\n[WinXP]command.com\nComsol\ncsh\n" - "Delphi\nEiffel\nElan\nEuphoria\nFortran\n[77]Fortran\n[90]Fortran\n" + "Delphi\nEiffel\nElan\nerlang\nEuphoria\nFortran\n[77]Fortran\n[90]Fortran\n" "[95]Fortran\nGCL\nGnuplot\nHaskell\nHTML\nIDL\n[CORBA]IDL\ninform\n" "Java\n[AspectJ]Java\nJVMIS\nksh\nLingo\nLisp\n[Auto]Lisp\nLogo\n" "make\n[gnu]make\nMathematica\n[1.0]Mathematica\n[3.0]Mathematica\n" @@ -259,7 +273,7 @@ char const * allowed_languages = /// ListingsParam Validator. -/// This class is aimed to be a singleton which is instantiated in +/// This class is aimed to be a singleton which is instantiated in /// \c InsetListingsParams::addParam(). // FIXME: transfer this validator to the frontend. // FIXME: avoid the use of exception. @@ -268,22 +282,18 @@ class ParValidator public: ParValidator(); - /// \return the associated \c ListingsParam. - /// \warning an \c invalidParamexception will be thrown - /// if the key is not found. - ListingsParam const & param(string const & key) const; + /// validate a parameter for a given name. + /// return an error message if \c par is an invalid parameter. + docstring validate(string const & name, string const & par) const; - /// validate a parameter for a given key. - /// \warning an \c invalidParam exception will be thrown if - /// \c par is an invalid parameter. - ListingsParam const & validate(string const & key, string const & par) const; + /// return the onoff status of a parameter \c key, if \c key is not found + /// return false + bool onoff(string const & key) const; private: /// key is the name of the parameter typedef map ListingsParams; ListingsParams all_params_; - /// - string all_param_names_; }; @@ -301,337 +311,403 @@ ParValidator::ParValidator() /// options copied from page 26 of listings manual // FIXME: add default parameters ... (which is not used now) - all_params_["float"] = + all_params_["float"] = ListingsParam("false", true, SUBSETOF, "*tbph", empty_hint); - all_params_["floatplacement"] = + all_params_["floatplacement"] = ListingsParam("tbp", false, SUBSETOF, "tbp", empty_hint); - all_params_["aboveskip"] = - ListingsParam("\\medskipamount", false, LENGTH, "", empty_hint); - all_params_["belowskip"] = - ListingsParam("\\medskipamount", false, LENGTH, "", empty_hint); - all_params_["lineskip"] = - ListingsParam("", false, LENGTH, "", empty_hint); - all_params_["boxpos"] = + all_params_["aboveskip"] = + ListingsParam("\\medskipamount", false, SKIP, "", empty_hint); + all_params_["belowskip"] = + ListingsParam("\\medskipamount", false, SKIP, "", empty_hint); + all_params_["lineskip"] = + ListingsParam("", false, SKIP, "", empty_hint); + all_params_["boxpos"] = ListingsParam("", false, SUBSETOF, "bct", empty_hint); - all_params_["print"] = + all_params_["print"] = ListingsParam("", false, TRUEFALSE, "", empty_hint); - all_params_["firstline"] = + all_params_["firstline"] = ListingsParam("", false, INTEGER, "", empty_hint); - all_params_["lastline"] = + all_params_["lastline"] = ListingsParam("", false, INTEGER, "", empty_hint); + all_params_["linerange"] = + ListingsParam("", false, ALL, "", empty_hint); all_params_["showlines"] = ListingsParam("", false, TRUEFALSE, "", empty_hint); - all_params_["emptylines"] = + all_params_["emptylines"] = ListingsParam("", false, ALL, "", _( "Expect a number with an optional * before it")); - all_params_["gobble"] = + all_params_["gobble"] = ListingsParam("", false, INTEGER, "", empty_hint); - all_params_["style"] = + all_params_["style"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["language"] = + all_params_["language"] = ListingsParam("", false, ONEOF, allowed_languages, empty_hint); - all_params_["alsolanguage"] = + all_params_["alsolanguage"] = ListingsParam("", false, ONEOF, allowed_languages, empty_hint); - all_params_["defaultdialect"] = + all_params_["defaultdialect"] = ListingsParam("", false, ONEOF, allowed_languages, empty_hint); - all_params_["printpod"] = + all_params_["printpod"] = ListingsParam("", false, TRUEFALSE, "", empty_hint); - all_params_["usekeywordsintag"] = + all_params_["usekeywordsintag"] = ListingsParam("", false, TRUEFALSE, "", empty_hint); - all_params_["tagstyle"] = + all_params_["tagstyle"] = ListingsParam("", false, ALL, "", style_hint); - all_params_["markfirstintag"] = + all_params_["markfirstintag"] = ListingsParam("", false, ALL, "", style_hint); - all_params_["makemacrouse"] = + all_params_["makemacrouse"] = ListingsParam("", false, TRUEFALSE, "", empty_hint); - all_params_["basicstyle"] = + all_params_["basicstyle"] = ListingsParam("", false, ALL, "", style_hint); - all_params_["identifierstyle"] = + all_params_["identifierstyle"] = ListingsParam("", false, ALL, "", style_hint); - all_params_["commentstyle"] = + all_params_["commentstyle"] = ListingsParam("", false, ALL, "", style_hint); - all_params_["stringstyle"] = + all_params_["stringstyle"] = ListingsParam("", false, ALL, "", style_hint); - all_params_["keywordstyle"] = + all_params_["keywordstyle"] = ListingsParam("", false, ALL, "", style_hint); - all_params_["ndkeywordstyle"] = + all_params_["ndkeywordstyle"] = ListingsParam("", false, ALL, "", style_hint); - all_params_["classoffset"] = + all_params_["classoffset"] = ListingsParam("", false, INTEGER, "", empty_hint); - all_params_["texcsstyle"] = + all_params_["texcsstyle"] = ListingsParam("", false, ALL, "", style_hint); - all_params_["directivestyle"] = + all_params_["directivestyle"] = ListingsParam("", false, ALL, "", style_hint); - all_params_["emph"] = + all_params_["emph"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["moreemph"] = + all_params_["moreemph"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["deleteemph"] = + all_params_["deleteemph"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["emphstyle"] = + all_params_["emphstyle"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["delim"] = + all_params_["delim"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["moredelim"] = + all_params_["moredelim"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["deletedelim"] = + all_params_["deletedelim"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["extendedchars"] = + all_params_["extendedchars"] = ListingsParam("", false, TRUEFALSE, "", empty_hint); - all_params_["inputencoding"] = + all_params_["inputencoding"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["upquote"] = + all_params_["upquote"] = ListingsParam("", false, TRUEFALSE, "", empty_hint); - all_params_["tabsize"] = + all_params_["tabsize"] = ListingsParam("", false, INTEGER, "", empty_hint); - all_params_["showtabs"] = + all_params_["showtabs"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["tab"] = + all_params_["tab"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["showspaces"] = + all_params_["showspaces"] = ListingsParam("", false, TRUEFALSE, "", empty_hint); - all_params_["showstringspaces"] = + all_params_["showstringspaces"] = ListingsParam("", false, TRUEFALSE, "", empty_hint); - all_params_["formfeed"] = + all_params_["formfeed"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["numbers"] = + all_params_["numbers"] = ListingsParam("", false, ONEOF, "none\nleft\nright", empty_hint); - all_params_["stepnumber"] = + all_params_["stepnumber"] = ListingsParam("", false, INTEGER, "", empty_hint); - all_params_["numberfirstline"] = + all_params_["numberfirstline"] = ListingsParam("", false, TRUEFALSE, "", empty_hint); - all_params_["numberstyle"] = + all_params_["numberstyle"] = ListingsParam("", false, ALL, "", style_hint); - all_params_["numbersep"] = + all_params_["numbersep"] = ListingsParam("", false, LENGTH, "", empty_hint); - all_params_["numberblanklines"] = + all_params_["numberblanklines"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["firstnumber"] = + all_params_["firstnumber"] = ListingsParam("", false, ALL, "", _("auto, last or a number")); - all_params_["name"] = + all_params_["name"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["thelstnumber"] = + all_params_["thelstnumber"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["title"] = + all_params_["title"] = ListingsParam("", false, ALL, "", empty_hint); // this option is not handled in the parameter box - all_params_["caption"] = + all_params_["caption"] = ListingsParam("", false, ALL, "", _( - "This parameter should not be entered here. Please use caption " - "editbox (Include dialog) or insert->caption (listings inset)")); + "This parameter should not be entered here. Please use the caption " + "edit box (when using the child document dialog) or " + "menu Insert->Caption (when defining a listing inset)")); // this option is not handled in the parameter box - all_params_["label"] = + all_params_["label"] = ListingsParam("", false, ALL, "",_( - "This parameter should not be entered here. Please use label " - "editbox (Include dialog) or insert->caption (listings inset)")); - all_params_["nolol"] = + "This parameter should not be entered here. Please use the label " + "edit box (when using the child document dialog) or " + "menu Insert->Label (when defining a listing inset)")); + all_params_["nolol"] = ListingsParam("", false, TRUEFALSE, "", empty_hint); - all_params_["captionpos"] = + all_params_["captionpos"] = ListingsParam("", false, SUBSETOF, "tb", empty_hint); - all_params_["abovecaptionskip"] = + all_params_["abovecaptionskip"] = + ListingsParam("", false, SKIP, "", empty_hint); + all_params_["belowcaptionskip"] = + ListingsParam("", false, SKIP, "", empty_hint); + all_params_["linewidth"] = ListingsParam("", false, LENGTH, "", empty_hint); - all_params_["belowcaptionskip"] = + all_params_["xleftmargin"] = ListingsParam("", false, LENGTH, "", empty_hint); - all_params_["linewidth"] = + all_params_["xrightmargin"] = ListingsParam("", false, LENGTH, "", empty_hint); - all_params_["xleftmargin"] = - ListingsParam("", false, LENGTH, "", empty_hint); - all_params_["xrightmargin"] = - ListingsParam("", false, LENGTH, "", empty_hint); - all_params_["resetmargins"] = + all_params_["resetmargins"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_["breaklines"] = ListingsParam("", false, TRUEFALSE, "", empty_hint); - all_params_["breaklines"] = + all_params_["breakatwhitespace"] = ListingsParam("", false, TRUEFALSE, "", empty_hint); - all_params_["prebreak"] = + all_params_["prebreak"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["postbreak"] = + all_params_["postbreak"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["breakindent"] = + all_params_["breakindent"] = ListingsParam("", false, LENGTH, "", empty_hint); - all_params_["breakautoindent"] = + all_params_["breakautoindent"] = ListingsParam("", false, TRUEFALSE, "", empty_hint); - all_params_["frame"] = + all_params_["frame"] = ListingsParam("", false, ALL, "", frame_hint); - all_params_["frameround"] = + all_params_["frameround"] = ListingsParam("", false, SUBSETOF, "tf", frameround_hint); - all_params_["framesep"] = + all_params_["framesep"] = ListingsParam("", false, LENGTH, "", empty_hint); - all_params_["rulesep"] = + all_params_["rulesep"] = ListingsParam("", false, LENGTH, "", empty_hint); - all_params_["framerule"] = + all_params_["framerule"] = ListingsParam("", false, LENGTH, "", empty_hint); - all_params_["framexleftmargin"] = + all_params_["framexleftmargin"] = ListingsParam("", false, LENGTH, "", empty_hint); - all_params_["framexrightmargin"] = + all_params_["framexrightmargin"] = ListingsParam("", false, LENGTH, "", empty_hint); - all_params_["framextopmargin"] = + all_params_["framextopmargin"] = ListingsParam("", false, LENGTH, "", empty_hint); - all_params_["framexbottommargin"] = + all_params_["framexbottommargin"] = ListingsParam("", false, LENGTH, "", empty_hint); - all_params_["backgroundcolor"] = + all_params_["backgroundcolor"] = ListingsParam("", false, ALL, "", color_hint ); - all_params_["rulecolor"] = + all_params_["rulecolor"] = ListingsParam("", false, ALL, "", color_hint ); - all_params_["fillcolor"] = + all_params_["fillcolor"] = ListingsParam("", false, ALL, "", color_hint ); - all_params_["rulesepcolor"] = + all_params_["rulesepcolor"] = ListingsParam("", false, ALL, "", color_hint ); - all_params_["frameshape"] = + all_params_["frameshape"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["index"] = + all_params_["index"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["moreindex"] = + all_params_["moreindex"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["deleteindex"] = + all_params_["deleteindex"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["indexstyle"] = + all_params_["indexstyle"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["columns"] = + all_params_["columns"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["flexiblecolumns"] = + all_params_["flexiblecolumns"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["keepspaces"] = + all_params_["keepspaces"] = ListingsParam("", false, TRUEFALSE, "", empty_hint); - all_params_["basewidth"] = + all_params_["basewidth"] = ListingsParam("", false, LENGTH, "", empty_hint); - all_params_["fontadjust"] = + all_params_["fontadjust"] = ListingsParam("", true, TRUEFALSE, "", empty_hint); - all_params_["texcl"] = + all_params_["texcl"] = ListingsParam("", false, TRUEFALSE, "", empty_hint); - all_params_["mathescape"] = + all_params_["mathescape"] = ListingsParam("", false, TRUEFALSE, "", empty_hint); - all_params_["escapechar"] = + all_params_["escapechar"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["escapeinside"] = + all_params_["escapeinside"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["escepeinside"] = + all_params_["escapebegin"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["escepebegin"] = + all_params_["escapeend"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["escepeend"] = - ListingsParam("", false, ALL, "", empty_hint); - all_params_["fancyvrb"] = + all_params_["fancyvrb"] = ListingsParam("", false, TRUEFALSE, "", empty_hint); - all_params_["fvcmdparams"] = + all_params_["fvcmdparams"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["morefvcmdparams"] = + all_params_["morefvcmdparams"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["keywordsprefix"] = + all_params_["keywordsprefix"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["keywords"] = + all_params_["keywords"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["morekeywords"] = + all_params_["morekeywords"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["deletekeywords"] = + all_params_["deletekeywords"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["ndkeywords"] = + all_params_["ndkeywords"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["morendkeywords"] = + all_params_["morendkeywords"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["deletendkeywords"] = + all_params_["deletendkeywords"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["texcs"] = + all_params_["texcs"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["moretexcs"] = + all_params_["moretexcs"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["deletetexcs"] = + all_params_["deletetexcs"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["directives"] = + all_params_["directives"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["moredirectives"] = + all_params_["moredirectives"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["deletedirectives"] = + all_params_["deletedirectives"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["sensitive"] = + all_params_["sensitive"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["alsoletter"] = + all_params_["alsoletter"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["alsodigit"] = + all_params_["alsodigit"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["alsoother"] = + all_params_["alsoother"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["otherkeywords"] = + all_params_["otherkeywords"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["tag"] = + all_params_["tag"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["string"] = + all_params_["string"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["morestring"] = + all_params_["morestring"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["deletestring"] = + all_params_["deletestring"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["comment"] = + all_params_["comment"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["morecomment"] = + all_params_["morecomment"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["deletecomment"] = + all_params_["deletecomment"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["keywordcomment"] = + all_params_["keywordcomment"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["morekeywordcomment"] = + all_params_["morekeywordcomment"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["deletekeywordcomment"] = + all_params_["deletekeywordcomment"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["keywordcommentsemicolon"] = + all_params_["keywordcommentsemicolon"] = ListingsParam("", false, ALL, "", empty_hint); - all_params_["podcomment"] = + all_params_["podcomment"] = ListingsParam("", false, ALL, "", empty_hint); - - ListingsParams::const_iterator it = all_params_.begin(); - ListingsParams::const_iterator end = all_params_.end(); - for (; it != end; ++it) { - if (!all_param_names_.empty()) - all_param_names_ += ", "; - all_param_names_ += it->first; - } + // the following are experimental listings features + all_params_["procnamekeys"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_["moreprocnamekeys"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_["deleteprocnamekeys"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_["procnamestyle"] = + ListingsParam("", false, ALL, "", style_hint); + all_params_["indexprocnames"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_["hyperref"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_["morehyperref"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_["deletehyperref"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_["hyperanchor"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_["hyperlink"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_["literate"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_["lgrindef"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_["rangebeginprefix"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_["rangebeginsuffix"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_["rangeendprefix"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_["rangeendsuffix"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_["rangeprefix"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_["rangesuffix"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_["includerangemarker"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_["multicols"] = + ListingsParam("", false, INTEGER, "", empty_hint); } -ListingsParam const & ParValidator::validate(string const & key, +docstring ParValidator::validate(string const & name, string const & par) const { - ListingsParam const & lparam = param(key); - docstring s = lparam.validate(par); - if (!s.empty()) - throw invalidParam(bformat(_("Parameter %1$s: "), from_utf8(key)) + s); - return lparam; + if (name.empty()) + return _("Invalid (empty) listing parameter name."); + + if (name[0] == '?') { + string suffix = trim(string(name, 1)); + string param_names; + ListingsParams::const_iterator it = all_params_.begin(); + ListingsParams::const_iterator end = all_params_.end(); + for (; it != end; ++it) { + if (suffix.empty() || contains(it->first, suffix)) { + if (!param_names.empty()) + param_names += ", "; + param_names += it->first; + } + } + if (suffix.empty()) + return bformat( + _("Available listing parameters are %1$s"), from_ascii(param_names)); + else + return bformat( + _("Available listings parameters containing string \"%1$s\" are %2$s"), + from_utf8(suffix), from_utf8(param_names)); + } + + // locate name in parameter table + ListingsParams::const_iterator it = all_params_.find(name); + if (it != all_params_.end()) { + docstring msg = it->second.validate(par); + if (msg.empty()) + return msg; + else + return bformat(_("Parameter %1$s: "), from_utf8(name)) + msg; + } else { + // otherwise, produce a meaningful error message. + string matching_names; + ListingsParams::const_iterator end = all_params_.end(); + for (it = all_params_.begin(); it != end; ++it) { + if (prefixIs(it->first, name)) { + if (!matching_names.empty()) + matching_names += ", "; + matching_names += it->first; + } + } + if (matching_names.empty()) + return bformat(_("Unknown listing parameter name: %1$s"), + from_utf8(name)); + else + return bformat(_("Parameters starting with '%1$s': %2$s"), + from_utf8(name), from_utf8(matching_names)); + } + // this stifles a warning but upsets coverity + // coverity[UNREACHABLE] + return docstring(); } -ListingsParam const & ParValidator::param(string const & name) const +bool ParValidator::onoff(string const & name) const { - if (name.empty()) - throw invalidParam(_("Invalid (empty) listings param name.")); - - if (name == "?") - throw invalidParam(bformat( - _("Available listings parameters are %1$s"), from_ascii(all_param_names_))); - // locate name in parameter table ListingsParams::const_iterator it = all_params_.find(name); if (it != all_params_.end()) - return it->second; - - // otherwise, produce a meaningful error message. - string matching_names; - ListingsParams::const_iterator end = all_params_.end(); - for (it = all_params_.begin(); it != end; ++it) { - if (prefixIs(it->first, name)) { - if (!matching_names.empty()) - matching_names += ", "; - matching_names += it->first; - } - } - if (matching_names.empty()) - throw invalidParam(bformat(_("Unknown listings param name: %1$s"), - from_utf8(name))); + return it->second.onoff_; else - throw invalidParam(bformat(_("Parameters starting with '%1$s': %2$s"), - from_utf8(name), from_utf8(matching_names))); + return false; } } // namespace anon. +// define a global ParValidator +ParValidator * par_validator = 0; + InsetListingsParams::InsetListingsParams() : inline_(false), params_(), status_(InsetCollapsable::Open) { @@ -660,10 +736,9 @@ void InsetListingsParams::write(ostream & os) const void InsetListingsParams::read(Lexer & lex) { lex >> inline_; - int s; + int s = InsetCollapsable::Collapsed; lex >> s; - if (lex) - status_ = static_cast(s); + status_ = static_cast(s); string par; lex >> par; fromEncodedString(par); @@ -673,52 +748,76 @@ void InsetListingsParams::read(Lexer & lex) string InsetListingsParams::params(string const & sep) const { string par; - for (map::const_iterator it = params_.begin(); - it != params_.end(); ++it) { + keyValuePair::const_iterator it = params_.begin(); + for (; it != params_.end(); ++it) { if (!par.empty()) par += sep; + // key=value,key=value1 is stored in params_ as key=value,key_=value1. if (it->second.empty()) - par += it->first; + par += rtrim(it->first, "_"); else - par += it->first + '=' + it->second; + par += rtrim(it->first, "_") + '=' + it->second; } return par; } -void InsetListingsParams::addParam(string const & key, string const & value) -{ +bool InsetListingsParams::hasParam(string const & key) const +{ + keyValuePair::const_iterator it = params_.begin(); + for (; it != params_.end(); ++it) { + if (it->first == key) + return true; + } + return false; +} + + +string InsetListingsParams::getValue(string const & key) const +{ + keyValuePair::const_iterator it = params_.begin(); + for (; it != params_.end(); ++it) { + if (it->first == key) + return it->second; + } + return string(); +} + + +void InsetListingsParams::addParam(string const & key, + string const & value, bool replace) +{ if (key.empty()) return; - static ParValidator par_validator; - - // exception may be thown. - ListingsParam const & lparam = par_validator.validate(key, value); // duplicate parameters! - if (params_.find(key) != params_.end()) - throw invalidParam(bformat(_("Parameter %1$s has already been defined"), - from_utf8(key))); + string keyname = key; + if (!replace && hasParam(key)) + // key=value,key=value1 is allowed in listings + // use key_, key__, key___ etc to avoid name conflict + while (hasParam(keyname += '_')) { } // check onoff flag // onoff parameter with value false - if (lparam.onoff_ && (value == "false" || value == "{false}")) - params_[key] = string(); + if (!par_validator) + par_validator = new ParValidator; + if (par_validator->onoff(key) && (value == "false" || value == "{false}")) + params_.push_back(make_pair(keyname, string())); // if the parameter is surrounded with {}, good else if (prefixIs(value, "{") && suffixIs(value, "}")) - params_[key] = value; - // otherwise, check if {} is needed. Add {} to all values with + params_.push_back(make_pair(keyname, value)); + // otherwise, check if {} is needed. Add {} to all values with // non-ascii/number characters, just to be safe else { bool has_special_char = false; for (size_t i = 0; i < value.size(); ++i) - if (!isAlphaASCII(value[i]) && !isDigit(value[i])) { + if (!isAlnumASCII(value[i])) { has_special_char = true; break; } if (has_special_char) - params_[key] = "{" + value + "}"; + params_.push_back(make_pair(keyname, "{" + value + "}")); else - params_[key] = value; + params_.push_back(make_pair(keyname, value)); } } @@ -746,12 +845,13 @@ void InsetListingsParams::addParams(string const & par) } else if (par[i] == '=' && braces == 0) { isValue = true; continue; - } else if (par[i] == '{' && par[i - 1] == '=') - braces ++; - else if (par[i] == '}' - && (i == par.size() - 1 || par[i + 1] == ',' || par[i + 1] == '\n')) - braces --; - + } else if (par[i] == '{' && i > 0 && par[i-1] != '\\') + // don't count a brace in first position + ++braces; + else if (par[i] == '}' && i != par.size() - 1 + && (i == 0 || (i > 0 && par[i-1] != '\\'))) + --braces; + if (isValue) value += par[i]; else @@ -772,14 +872,14 @@ void InsetListingsParams::setParams(string const & par) string InsetListingsParams::encodedString() const { // Encode string! - // '"' is handled differently because it will + // '"' is handled differently because it will // terminate a lyx token. string par = params(); // '"' is now " ==> '"' is now &quot; par = subst(par, "&", "&"); // '"' is now &quot; ==> '"' is now &quot; par = subst(par, "\"", """); - return par; + return par; } @@ -806,16 +906,34 @@ void InsetListingsParams::fromEncodedString(string const & in) bool InsetListingsParams::isFloat() const { - return params_.find("float") != params_.end(); + return hasParam("float"); } string InsetListingsParams::getParamValue(string const & param) const { - // is this parameter defined? - map::const_iterator it = params_.find(param); - return (it == params_.end()) ? string() : it->second; + string par = getValue(param); + if (prefixIs(par, "{") && suffixIs(par, "}")) + return par.substr(1, par.size() - 2); + else + return par; } +docstring InsetListingsParams::validate() const +{ + docstring msg; + if (!par_validator) + par_validator = new ParValidator; + // return msg for first key=value pair which is incomplete or has an error + keyValuePair::const_iterator it = params_.begin(); + for (; it != params_.end(); ++it) { + // key trimmed + msg = par_validator->validate(rtrim(it->first, "_"), it->second); + if (!msg.empty()) + return msg; + } + return msg; +} + } // namespace lyx