X-Git-Url: https://git.lyx.org/gitweb/?a=blobdiff_plain;f=src%2Finsets%2FInsetListingsParams.cpp;h=998554c395c7f3f6e33c4798c2fb469b3b6e0c36;hb=b7ec3d8515b539260a16e9c5987c4116f4d1257c;hp=300e531e0d10db89e813b7b8eafbdbe507396ac9;hpb=cddcdd08ea30fed7c6f6e5f3cfee15f5d3a72c5e;p=lyx.git diff --git a/src/insets/InsetListingsParams.cpp b/src/insets/InsetListingsParams.cpp index 300e531e0d..998554c395 100644 --- a/src/insets/InsetListingsParams.cpp +++ b/src/insets/InsetListingsParams.cpp @@ -9,406 +9,208 @@ */ #include +#include -#include "Lexer.h" #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 -#include -#include "support/lstrings.h" -#include "support/convert.h" +using namespace std; +using namespace lyx::support; -using std::vector; -using std::ostream; -using std::string; -using std::exception; -using lyx::support::trim; -using lyx::support::isStrInt; -using lyx::support::prefixIs; -using lyx::support::suffixIs; -using lyx::support::getVectorFromString; - -namespace lyx -{ +namespace lyx { + +namespace { enum param_type { ALL, // accept all TRUEFALSE, // accept 'true' or 'false' INTEGER, // accept an integer - LENGTH, // accept an latex length + 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 }; -/** Information about each parameter - */ -struct listings_param_info { - /// name of the parameter - char const * name; +/// Listings package parameter information. +// FIXME: make this class visible outside of this file so that +// FIXME: it can be used directly in the frontend and in the LyX format +// FIXME: parsing. +class ListingsParam { +public: + /// Default ctor for STL containers. + ListingsParam(): onoff_(false), type_(ALL) + {} + /// Main ctor. + ListingsParam(string const & v, bool o, param_type t, + string const & i, docstring const & h) + : value_(v), onoff_(o), type_(t), info_(i), hint_(h) + {} + /// Validate a paramater. + /// \retval an empty string if \c par is valid. + /// \retval otherwise an explanation WRT to \c par invalidity. + docstring validate(string const & par) const; +private: /// default value - char const * value; - // for option with value "true", "false", - // if onoff is true, - // "true": option - // "false": - // "other": option="other" - // onoff is false, - // "true": option=true - // "false": option=false - bool onoff; - /// validator type - param_type type; - // ALL: - // TRUEFALSE: - // INTEGER: - // LENGTH: - // info is ignored. - // ONEOF - // info is a \n separated string with allowed values - // SUBSETOF - // info is a string from which par is composed of - // (e.g. floatplacement can be one or more of tbph) - char const * info; - // - char const * hint; -}; - - - -/// languages and language/dialect combinations -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" - "[Motorola68k]Assembler\n[x86masm]Assembler\nAwk\n[gnu]Awk\n[POSIX]Awk\n" - "bash\nBasic\n[Visual]Basic\nC\n[ANSI]C\n[Handel]C\n[Objective]C\n" - "[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" - "[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" - "[5.2]Mathematica\nMatlab\nMercury\nMetaPost\nMiranda\nMizar\nML\n" - "Modula-2\nMuPAD\nNASTRAN\nOberon-2\nOCL\n[decorative]OCL\n[OMG]OCL\n" - "Octave\nOz\nPascal\n[Borland6]Pascal\n[Standard]Pascal\n[XSC]Pascal\n" - "Perl\nPHP\nPL/I\nPlasm\nPostScript\nPOV\nProlog\nPromela\nPSTricks\n" - "Python\nR\nReduce\nRexx\nRSL\nRuby\nS\n[PLUS]S\nSAS\nScilab\nsh\n" - "SHELXL\nSimula\n[67]Simula\n[CII]Simula\n[DEC]Simula\n[IBM]Simula\n" - "SPARQL\nSQL\ntcl\n[tk]tcl\nTeX\n[AlLaTeX]TeX\n[common]TeX\n[LaTeX]TeX\n" - "[plain]TeX\n[primitive]TeX\nVBScript\nVerilog\nVHDL\n[AMS]VHDL\nVRML\n" - "[97]VRML\nXML\nXSLT"; - -char const * style_hint = "Use \\footnotesize, \\small, \\itshape, \\ttfamily or something like that"; -char const * frame_hint = "none, leftline, topline, bottomline, lines, single, shadowbox or subset of trblTRBL"; -char const * frameround_hint = - "Enter four letters (either t = round or f = square) for top right, bottom right, bottom left and top left corner."; -char const * color_hint = "Enter something like \\color{white}"; - -/// options copied from page 26 of listings manual -// FIXME: add default parameters ... (which is not used now) -listings_param_info const listings_param_table[] = { - { "float", "false", true, SUBSETOF, "tbph", "" }, - { "floatplacement", "tbp", false, SUBSETOF, "tbph", "" }, - { "aboveskip", "\\medskipamount", false, LENGTH, "", "" }, - { "belowskip", "\\medskipamount", false, LENGTH, "", "" }, - { "lineskip", "", false, LENGTH, "", "" }, - { "boxpos", "", false, SUBSETOF, "bct", "" }, - { "print", "", false, TRUEFALSE, "", "" }, - { "firstline", "", false, INTEGER, "", "" }, - { "lastline", "", false, INTEGER, "", "" }, - { "showlines", "", false, TRUEFALSE, "", "" }, - { "emptylines", "", false, ALL, "", "Expect a number with an optional * before it" }, - { "gobble", "", false, INTEGER, "", "" }, - { "style", "", false, ALL, "", "" }, - { "language", "", false, ONEOF, allowed_languages, "" }, - { "alsolanguage", "", false, ONEOF, allowed_languages, "" }, - { "defaultdialect", "", false, ONEOF, allowed_languages, "" }, - { "printpod", "", false, TRUEFALSE, "", "" }, - { "usekeywordsintag", "", false, TRUEFALSE, "", "" }, - { "tagstyle", "", false, ALL, "", style_hint }, - { "markfirstintag", "", false, ALL, "", style_hint }, - { "makemacrouse", "", false, TRUEFALSE, "", "" }, - { "basicstyle", "", false, ALL, "", style_hint }, - { "identifierstyle", "", false, ALL, "", style_hint }, - { "commentstyle", "", false, ALL, "", style_hint }, - { "stringstyle", "", false, ALL, "", style_hint }, - { "keywordstyle", "", false, ALL, "", style_hint }, - { "ndkeywordstyle", "", false, ALL, "", style_hint }, - { "classoffset", "", false, INTEGER, "", "" }, - { "texcsstyle", "", false, ALL, "", style_hint }, - { "directivestyle", "", false, ALL, "", style_hint }, - { "emph", "", false, ALL, "", "" }, - { "moreemph", "", false, ALL, "", "" }, - { "deleteemph", "", false, ALL, "", "" }, - { "emphstyle", "", false, ALL, "", "" }, - { "delim", "", false, ALL, "", "" }, - { "moredelim", "", false, ALL, "", "" }, - { "deletedelim", "", false, ALL, "", "" }, - { "extendedchars", "", false, TRUEFALSE, "", "" }, - { "inputencoding", "", false, ALL, "", "" }, - { "upquote", "", false, TRUEFALSE, "", "" }, - { "tabsize", "", false, INTEGER, "", "" }, - { "showtabs", "", false, ALL, "", "" }, - { "tab", "", false, ALL, "", "" }, - { "showspaces", "", false, TRUEFALSE, "", "" }, - { "showstringspaces", "", false, TRUEFALSE, "", "" }, - { "formfeed", "", false, ALL, "", "" }, - { "numbers", "", false, ONEOF, "none\nleft\nright", "" }, - { "stepnumber", "", false, INTEGER, "", "" }, - { "numberfirstline", "", false, TRUEFALSE, "", "" }, - { "numberstyle", "", false, ALL, "", style_hint }, - { "numbersep", "", false, LENGTH, "", "" }, - { "numberblanklines", "", false, ALL, "", "" }, - { "firstnumber", "", false, ALL, "", "auto, last or a number" }, - { "name", "", false, ALL, "", "" }, - { "thelstnumber", "", false, ALL, "", "" }, - { "title", "", false, ALL, "", "" }, - // this option is not handled in the parameter box - { "caption", "", false, ALL, "", "This parameter should not be entered here. " - "Please use caption editbox (Include dialog) or insert->caption (listings inset)" }, - // this option is not handled in the parameter box - { "label", "", false, ALL, "", "This parameter should not be entered here." - "Please use label editbox (Include dialog) or insert->caption (listings inset)"}, - { "nolol", "", false, TRUEFALSE, "", "" }, - { "captionpos", "", false, SUBSETOF, "tb", "" }, - { "abovecaptionskip", "", false, LENGTH, "", "" }, - { "belowcaptionskip", "", false, LENGTH, "", "" }, - { "linewidth", "", false, LENGTH, "", "" }, - { "xleftmargin", "", false, LENGTH, "", "" }, - { "xrightmargin", "", false, LENGTH, "", "" }, - { "resetmargins", "", false, TRUEFALSE, "", "" }, - { "breaklines", "", false, TRUEFALSE, "", "" }, - { "prebreak", "", false, ALL, "", "" }, - { "postbreak", "", false, ALL, "", "" }, - { "breakindent", "", false, LENGTH, "", "" }, - { "breakautoindent", "", false, TRUEFALSE, "", "" }, - { "frame", "", false, ALL, "", frame_hint }, - { "frameround", "", false, SUBSETOF, "tf", frameround_hint }, - { "framesep", "", false, LENGTH, "", "" }, - { "rulesep", "", false, LENGTH, "", "" }, - { "framerule", "", false, LENGTH, "", "" }, - { "framexleftmargin", "", false, LENGTH, "", "" }, - { "framexrightmargin", "", false, LENGTH, "", "" }, - { "framextopmargin", "", false, LENGTH, "", "" }, - { "framexbottommargin", "", false, LENGTH, "", "" }, - { "backgroundcolor", "", false, ALL, "", color_hint }, - { "rulecolor", "", false, ALL, "", color_hint }, - { "fillcolor", "", false, ALL, "", color_hint }, - { "rulesepcolor", "", false, ALL, "", color_hint }, - { "frameshape", "", false, ALL, "", "" }, - { "index", "", false, ALL, "", "" }, - { "moreindex", "", false, ALL, "", "" }, - { "deleteindex", "", false, ALL, "", "" }, - { "indexstyle", "", false, ALL, "", "" }, - { "columns", "", false, ALL, "", "" }, - { "flexiblecolumns", "", false, ALL, "", "" }, - { "keepspaces", "", false, TRUEFALSE, "", "" }, - { "basewidth", "", false, LENGTH, "", "" }, - { "fontadjust", "", true, TRUEFALSE, "", "" }, - { "texcl", "", false, TRUEFALSE, "", "" }, - { "mathescape", "", false, TRUEFALSE, "", "" }, - { "escapechar", "", false, ALL, "", "" }, - { "escapeinside", "", false, ALL, "", "" }, - { "escepeinside", "", false, ALL, "", "" }, - { "escepebegin", "", false, ALL, "", "" }, - { "escepeend", "", false, ALL, "", "" }, - { "fancyvrb", "", false, TRUEFALSE, "", "" }, - { "fvcmdparams", "", false, ALL, "", "" }, - { "morefvcmdparams", "", false, ALL, "", "" }, - { "keywordsprefix", "", false, ALL, "", "" }, - { "keywords", "", false, ALL, "", "" }, - { "morekeywords", "", false, ALL, "", "" }, - { "deletekeywords", "", false, ALL, "", "" }, - { "ndkeywords", "", false, ALL, "", "" }, - { "morendkeywords", "", false, ALL, "", "" }, - { "deletendkeywords", "", false, ALL, "", "" }, - { "texcs", "", false, ALL, "", "" }, - { "moretexcs", "", false, ALL, "", "" }, - { "deletetexcs", "", false, ALL, "", "" }, - { "directives", "", false, ALL, "", "" }, - { "moredirectives", "", false, ALL, "", "" }, - { "deletedirectives", "", false, ALL, "", "" }, - { "sensitive", "", false, ALL, "", "" }, - { "alsoletter", "", false, ALL, "", "" }, - { "alsodigit", "", false, ALL, "", "" }, - { "alsoother", "", false, ALL, "", "" }, - { "otherkeywords", "", false, ALL, "", "" }, - { "tag", "", false, ALL, "", "" }, - { "string", "", false, ALL, "", "" }, - { "morestring", "", false, ALL, "", "" }, - { "deletestring", "", false, ALL, "", "" }, - { "comment", "", false, ALL, "", "" }, - { "morecomment", "", false, ALL, "", "" }, - { "deletecomment", "", false, ALL, "", "" }, - { "keywordcomment", "", false, ALL, "", "" }, - { "morekeywordcomment", "", false, ALL, "", "" }, - { "deletekeywordcomment", "", false, ALL, "", "" }, - { "keywordcommentsemicolon", "", false, ALL, "", "" }, - { "podcomment", "", false, ALL, "", "" }, - { "", "", false, ALL, "", ""} -}; - - -class parValidator -{ + string value_; public: - parValidator(string const & name); - - /// validate given parameter - /// invalidParam will be thrown if invalid - /// parameter is found. - void validate(std::string const & par) const; - + /// for option with value "true", "false". + /// if onoff is true, + /// "true": option + /// "false": + /// "other": option="other" + /// onoff is false, + /// "true": option=true + /// "false": option=false + // FIXME: this is public because of InsetListingParam::addParam() + bool onoff_; private: - /// parameter name - string const & name; - /// - listings_param_info const * info; + /// validator type. + /// ALL: + /// TRUEFALSE: + /// INTEGER: + /// LENGTH: + /// info is ignored. + /// ONEOF + /// info is a \n separated string with allowed values + /// SUBSETOF + /// info is a string from which par is composed of + /// (e.g. floatplacement can be one or more of *tbph) + param_type type_; + /// information which meaning depends on parameter type. + /// \sa type_ + string info_; + /// a help message that is displayed in the gui. + docstring hint_; }; -parValidator::parValidator(string const & n) - : name(n), info(0) -{ - if (name.empty()) - throw invalidParam("Invalid (empty) listings param name."); - else if (name == "?") { - string pars; - size_t idx = 0; - while (listings_param_table[idx].name != string()) { - if (!pars.empty()) - pars += ", "; - pars += listings_param_table[idx].name; - ++idx; - } - throw invalidParam("Available listings parameters are " + pars); - } - // locate name in parameter table - size_t idx = 0; - while (listings_param_table[idx].name != name && listings_param_table[idx].name != string()) - ++idx; - // found the name - if (listings_param_table[idx].name != "") { - info = &listings_param_table[idx]; - return; - } - // otherwise, produce a meaningful error message. - string matching_names; - for (size_t i = 0; i < idx; ++i) { - string n(listings_param_table[i].name); - if (n.size() >= name.size() && n.substr(0, name.size()) == name) { - if (matching_names.empty()) - matching_names += n; - else - matching_names += ", " + n; - } - } - if (matching_names.empty()) - throw invalidParam("Unknown listings param name: " + name); - else - throw invalidParam("Parameters starting with '" + name + - "': " + matching_names); -} +char const * allowed_skips = "\\smallskipamount,\\medskipamount,\\bigskipamount"; -void parValidator::validate(std::string const & par) const +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; } - - - switch (info->type) { + unclosed = braces != 0; + + switch (type_) { + case ALL: - if (par2.empty() && !info->onoff) { - if (info->hint != "") - throw invalidParam(info->hint); + if (par2.empty() && !onoff_) { + if (!hint_.empty()) + return hint_; else - throw invalidParam("A value is expected"); + return _("A value is expected."); } if (unclosed) - throw invalidParam("Unbalanced braces!"); - return; - case TRUEFALSE: { - if (par2.empty() && !info->onoff) { - if (info->hint != "") - throw invalidParam(info->hint); + return _("Unbalanced braces!"); + return docstring(); + + case TRUEFALSE: + if (par2.empty() && !onoff_) { + if (!hint_.empty()) + return hint_; else - throw invalidParam("Please specify true or false"); + return _("Please specify true or false."); } if (par2 != "true" && par2 != "false") - throw invalidParam("Only true or false is allowed for parameter" + name); + return _("Only true or false is allowed."); if (unclosed) - throw invalidParam("Unbalanced braces!"); - return; - } - case INTEGER: { + return _("Unbalanced braces!"); + return docstring(); + + case INTEGER: if (!isStrInt(par2)) { - if (info->hint != "") - throw invalidParam(info->hint); + if (!hint_.empty()) + return hint_; else - throw invalidParam("Please specify an integer value"); + return _("Please specify an integer value."); } if (convert(par2) == 0 && par2[0] != '0') - throw invalidParam("An integer is expected for parameter " + name); + return _("An integer is expected."); if (unclosed) - throw invalidParam("Unbalanced braces!"); - return; - } - case LENGTH: { - if (par2.empty() && !info->onoff) { - if (info->hint != "") - throw invalidParam(info->hint); + return _("Unbalanced braces!"); + return docstring(); + + case LENGTH: + if (par2.empty() && !onoff_) { + if (!hint_.empty()) + return hint_; else - throw invalidParam("Please specify a latex length expression"); + return _("Please specify a LaTeX length expression."); } if (!isValidLength(par2)) - throw invalidParam("Invalid latex length expression for parameter " + name); + return _("Invalid LaTeX length expression."); if (unclosed) - throw invalidParam("Unbalanced braces!"); - return; - } + 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(); + case ONEOF: { - if (par2.empty() && !info->onoff) { - if (info->hint != "") - throw invalidParam(info->hint); + if (par2.empty() && !onoff_) { + if (!hint_.empty()) + return hint_; else - throw invalidParam("Please specify one of " + string(info->info)); + return bformat(_("Please specify one of %1$s."), + from_utf8(info_)); } // break value to allowed strings vector lists; string v; - for (size_t i = 0; info->info[i] != '\0'; ++i) { - if (info->info[i] == '\n') { + for (size_t i = 0; i != info_.size(); ++i) { + if (info_[i] == '\n') { lists.push_back(v); v = string(); } else - v += info->info[i]; + v += info_[i]; } if (!v.empty()) 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) - throw invalidParam("Unbalanced braces!"); - return; + 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()) @@ -418,38 +220,763 @@ void parValidator::validate(std::string const & par) const } } if (matching_names.empty()) - throw invalidParam("Try one of " + string(info->info)); + return bformat(_("Try one of %1$s."), from_utf8(info_)); else - throw invalidParam("I guess you mean " + matching_names); - return; + return bformat(_("I guess you mean %1$s."), from_utf8(matching_names)); } - case SUBSETOF: { - if (par2.empty() && !info->onoff) { - if (info->hint != "") - throw invalidParam(info->hint); + case SUBSETOF: + if (par2.empty() && !onoff_) { + if (!hint_.empty()) + return hint_; else - throw invalidParam("Please specify one or more of " + string(info->info)); + return bformat(_("Please specify one or more of '%1$s'."), + from_utf8(info_)); } for (size_t i = 0; i < par2.size(); ++i) - if (string(info->info).find(par2[i], 0) == string::npos) - throw invalidParam("Parameter " + name + - " should be composed of one or more of " + info->info); + if (info_.find(par2[i], 0) == string::npos) + return bformat(_("Should be composed of one or more of %1$s."), + from_utf8(info_)); if (unclosed) - throw invalidParam("Unbalanced braces!"); - return; + return _("Unbalanced braces!"); + return docstring(); + } + return docstring(); +} + + +/// languages and language/dialect combinations +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" + "[Motorola68k]Assembler\n[x86masm]Assembler\nAwk\n[gnu]Awk\n[POSIX]Awk\n" + "bash\nBasic\n[Visual]Basic\nC\n[ANSI]C\n[Handel]C\n[Objective]C\n" + "[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\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" + "[5.2]Mathematica\nMatlab\nMercury\nMetaPost\nMiranda\nMizar\nML\n" + "Modula-2\nMuPAD\nNASTRAN\nOberon-2\nOCL\n[decorative]OCL\n[OMG]OCL\n" + "Octave\nOz\nPascal\n[Borland6]Pascal\n[Standard]Pascal\n[XSC]Pascal\n" + "Perl\nPHP\nPL/I\nPlasm\nPostScript\nPOV\nProlog\nPromela\nPSTricks\n" + "Python\nR\nReduce\nRexx\nRSL\nRuby\nS\n[PLUS]S\nSAS\nScilab\nsh\n" + "SHELXL\nSimula\n[67]Simula\n[CII]Simula\n[DEC]Simula\n[IBM]Simula\n" + "SPARQL\nSQL\ntcl\n[tk]tcl\nTeX\n[AlLaTeX]TeX\n[common]TeX\n[LaTeX]TeX\n" + "[plain]TeX\n[primitive]TeX\nVBScript\nVerilog\nVHDL\n[AMS]VHDL\nVRML\n" + "[97]VRML\nXML\nXSLT"; + + +/// Return language allowed in the GUI without dialect and proper casing +string const languageonly(string const & lang) +{ + string const locase = ascii_lowercase(trim(lang, "{}")); + string const all_languages = ascii_lowercase(allowed_languages) + "\n"; + string language = (lang.at(0) == '[') ? locase + "\n" + : string("]") + locase + "\n"; + size_t i = all_languages.find(language); + if (i == string::npos && lang.at(0) != '[') { + language[0] = '\n'; + i = all_languages.find(language); } + if (i == string::npos) + return lang; + if (all_languages.at(i) == '[') + i = all_languages.find(']', i); + if (i == string::npos) + return lang; + size_t j = all_languages.find('\n', i + 1); + if (j == string::npos) + return lang; + return string(allowed_languages).substr(i + 1, j - i - 1); +} + + +/// ListingsParam Validator. +/// 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. +class ParValidator +{ +public: + ParValidator(); + + /// 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; + + /// 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_[2]; +}; + + +ParValidator::ParValidator() +{ + docstring const empty_hint; + docstring const style_hint = _("Use \\footnotesize, \\small, \\itshape, " + "\\ttfamily or something like that"); + docstring const frame_hint_mint = + _("none, leftline, topline, bottomline, lines, single"); + docstring const frame_hint_lst = + _("none, leftline, topline, bottomline, lines, " + "single, shadowbox or subset of trblTRBL"); + docstring const frameround_hint = _("Enter four letters (either t = round " + "or f = square) for top right, bottom " + "right, bottom left and top left corner."); + docstring const color_hint_mint = + _("Previously defined color name as a string"); + docstring const color_hint_lst = + _("Enter something like \\color{white}"); + + // Listings package + + /// options copied from page 26 of listings manual + // FIXME: add default parameters ... (which is not used now) + all_params_[0]["float"] = + ListingsParam("false", true, SUBSETOF, "*tbph", empty_hint); + all_params_[0]["floatplacement"] = + ListingsParam("tbp", false, SUBSETOF, "tbp", empty_hint); + all_params_[0]["aboveskip"] = + ListingsParam("\\medskipamount", false, SKIP, "", empty_hint); + all_params_[0]["belowskip"] = + ListingsParam("\\medskipamount", false, SKIP, "", empty_hint); + all_params_[0]["lineskip"] = + ListingsParam("", false, SKIP, "", empty_hint); + all_params_[0]["boxpos"] = + ListingsParam("", false, SUBSETOF, "bct", empty_hint); + all_params_[0]["print"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["firstline"] = + ListingsParam("", false, INTEGER, "", empty_hint); + all_params_[0]["lastline"] = + ListingsParam("", false, INTEGER, "", empty_hint); + all_params_[0]["linerange"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["showlines"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["emptylines"] = + ListingsParam("", false, ALL, "", _( + "Expect a number with an optional * before it")); + all_params_[0]["gobble"] = + ListingsParam("", false, INTEGER, "", empty_hint); + all_params_[0]["style"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["language"] = + ListingsParam("", false, ONEOF, allowed_languages, empty_hint); + all_params_[0]["alsolanguage"] = + ListingsParam("", false, ONEOF, allowed_languages, empty_hint); + all_params_[0]["defaultdialect"] = + ListingsParam("", false, ONEOF, allowed_languages, empty_hint); + all_params_[0]["printpod"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["usekeywordsintag"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["tagstyle"] = + ListingsParam("", false, ALL, "", style_hint); + all_params_[0]["markfirstintag"] = + ListingsParam("", false, ALL, "", style_hint); + all_params_[0]["makemacrouse"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["basicstyle"] = + ListingsParam("", false, ALL, "", style_hint); + all_params_[0]["identifierstyle"] = + ListingsParam("", false, ALL, "", style_hint); + all_params_[0]["commentstyle"] = + ListingsParam("", false, ALL, "", style_hint); + all_params_[0]["stringstyle"] = + ListingsParam("", false, ALL, "", style_hint); + all_params_[0]["keywordstyle"] = + ListingsParam("", false, ALL, "", style_hint); + all_params_[0]["ndkeywordstyle"] = + ListingsParam("", false, ALL, "", style_hint); + all_params_[0]["classoffset"] = + ListingsParam("", false, INTEGER, "", empty_hint); + all_params_[0]["texcsstyle"] = + ListingsParam("", false, ALL, "", style_hint); + all_params_[0]["directivestyle"] = + ListingsParam("", false, ALL, "", style_hint); + all_params_[0]["emph"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["moreemph"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["deleteemph"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["emphstyle"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["delim"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["moredelim"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["deletedelim"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["extendedchars"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["inputencoding"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["upquote"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["tabsize"] = + ListingsParam("", false, INTEGER, "", empty_hint); + all_params_[0]["showtabs"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["tab"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["showspaces"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["showstringspaces"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["formfeed"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["numbers"] = + ListingsParam("", false, ONEOF, "none\nleft\nright", empty_hint); + all_params_[0]["stepnumber"] = + ListingsParam("", false, INTEGER, "", empty_hint); + all_params_[0]["numberfirstline"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["numberstyle"] = + ListingsParam("", false, ALL, "", style_hint); + all_params_[0]["numbersep"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[0]["numberblanklines"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["firstnumber"] = + ListingsParam("", false, ALL, "", _("auto, last or a number")); + all_params_[0]["name"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["thelstnumber"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["title"] = + ListingsParam("", false, ALL, "", empty_hint); + // this option is not handled in the parameter box + all_params_[0]["caption"] = + ListingsParam("", false, ALL, "", _( + "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_[0]["label"] = + ListingsParam("", false, ALL, "",_( + "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_[0]["nolol"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["captionpos"] = + ListingsParam("", false, SUBSETOF, "tb", empty_hint); + all_params_[0]["abovecaptionskip"] = + ListingsParam("", false, SKIP, "", empty_hint); + all_params_[0]["belowcaptionskip"] = + ListingsParam("", false, SKIP, "", empty_hint); + all_params_[0]["linewidth"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[0]["xleftmargin"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[0]["xrightmargin"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[0]["resetmargins"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["breaklines"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["breakatwhitespace"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["prebreak"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["postbreak"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["breakindent"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[0]["breakautoindent"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["frame"] = + ListingsParam("", false, ALL, "", frame_hint_lst); + all_params_[0]["frameround"] = + ListingsParam("", false, SUBSETOF, "tf", frameround_hint); + all_params_[0]["framesep"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[0]["rulesep"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[0]["framerule"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[0]["framexleftmargin"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[0]["framexrightmargin"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[0]["framextopmargin"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[0]["framexbottommargin"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[0]["backgroundcolor"] = + ListingsParam("", false, ALL, "", color_hint_lst); + all_params_[0]["rulecolor"] = + ListingsParam("", false, ALL, "", color_hint_lst); + all_params_[0]["fillcolor"] = + ListingsParam("", false, ALL, "", color_hint_lst); + all_params_[0]["rulesepcolor"] = + ListingsParam("", false, ALL, "", color_hint_lst); + all_params_[0]["frameshape"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["index"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["moreindex"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["deleteindex"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["indexstyle"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["columns"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["flexiblecolumns"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["keepspaces"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["basewidth"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[0]["fontadjust"] = + ListingsParam("", true, TRUEFALSE, "", empty_hint); + all_params_[0]["texcl"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["mathescape"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["escapechar"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["escapeinside"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["escapebegin"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["escapeend"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["fancyvrb"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["fvcmdparams"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["morefvcmdparams"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["keywordsprefix"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["keywords"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["morekeywords"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["deletekeywords"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["ndkeywords"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["morendkeywords"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["deletendkeywords"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["texcs"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["moretexcs"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["deletetexcs"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["directives"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["moredirectives"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["deletedirectives"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["sensitive"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["alsoletter"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["alsodigit"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["alsoother"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["otherkeywords"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["tag"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["string"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["morestring"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["deletestring"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["comment"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["morecomment"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["deletecomment"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["keywordcomment"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["morekeywordcomment"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["deletekeywordcomment"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["keywordcommentsemicolon"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["podcomment"] = + ListingsParam("", false, ALL, "", empty_hint); + // the following are experimental listings features + all_params_[0]["procnamekeys"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["moreprocnamekeys"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["deleteprocnamekeys"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["procnamestyle"] = + ListingsParam("", false, ALL, "", style_hint); + all_params_[0]["indexprocnames"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["hyperref"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["morehyperref"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["deletehyperref"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["hyperanchor"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["hyperlink"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["literate"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["lgrindef"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["rangebeginprefix"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["rangebeginsuffix"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["rangeendprefix"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["rangeendsuffix"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["rangeprefix"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["rangesuffix"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[0]["includerangemarker"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[0]["multicols"] = + ListingsParam("", false, INTEGER, "", empty_hint); + + // Minted package + + // This is not a real minted option and its only purpose + // is to get a caption for a floating listing. + all_params_[1]["caption"] = + ListingsParam("", false, ALL, "", _( + "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)")); + // The "label" minted option is being subverted here for the + // sake of getting a label for a floating listing. + all_params_[1]["label"] = + ListingsParam("", false, ALL, "",_( + "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)")); + // This is not a real minted option and its only purpose + // is to signal that this is a floating listing. + all_params_[1]["float"] = + ListingsParam("false", true, SUBSETOF, "*tbph", empty_hint); + all_params_[1]["cache"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["cachedir"] = + ListingsParam("", false, ALL, "", _( + "default: _minted-")); + all_params_[1]["finalizecache"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["frozencache"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["draft"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["final"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["kpsewhich"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["langlinenos"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["newfloat"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["outputdir"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[1]["autogobble"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["baselinestretch"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[1]["breakafter"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[1]["breakaftergroup"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["breakaftersymbolpre"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[1]["breakaftersymbolpost"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[1]["breakanywhere"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["breakanywheresymbolpre"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[1]["breakanywheresymbolpost"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[1]["breakautoindent"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["breakbefore"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[1]["breakbeforegroup"] = + ListingsParam("", true, ALL, "", empty_hint); + all_params_[1]["breakbeforesymbolpre"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[1]["breakbeforesymbolpost"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[1]["breakbytoken"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["breakbytokenanywhere"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["breakindent"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[1]["breaklines"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["breaksymbol"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[1]["breaksymbolleft"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[1]["breaksymbolright"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[1]["breaksymbolindent"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[1]["breaksymbolindentleft"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[1]["breaksymbolindentright"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[1]["breaksymbolsep"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[1]["breaksymbolsepleft"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[1]["breaksymbolsepright"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[1]["bgcolor"] = + ListingsParam("", false, ALL, "", color_hint_mint); + all_params_[1]["codetagify"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[1]["curlyquotes"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["encoding"] = + ListingsParam("", false, ALL, "", _( + "Sets encoding expected by Pygments")); + all_params_[1]["escapeinside"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[1]["firstline"] = + ListingsParam("", false, INTEGER, "", empty_hint); + all_params_[1]["firstnumber"] = + ListingsParam("", false, ALL, "", _( + "auto, last or a number")); + all_params_[1]["fontfamily"] = + ListingsParam("", false, ALL, "", _( + "A latex family such as tt, sf, rm")); + all_params_[1]["fontseries"] = + ListingsParam("", false, ALL, "", _( + "A latex series such as m, b, c, bx, sb")); + all_params_[1]["fontsize"] = + ListingsParam("", false, ALL, "", _( + "A latex name such as \\small")); + all_params_[1]["fontshape"] = + ListingsParam("", false, ALL, "", _( + "A latex shape such as n, it, sl, sc")); + all_params_[1]["formatcom"] = + ListingsParam("", false, ALL, "", empty_hint); + all_params_[1]["frame"] = + ListingsParam("", false, ONEOF, + "none\nleftline\ntopline\nbottomline\nlines\nsingle", + frame_hint_mint); + all_params_[1]["framerule"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[1]["framesep"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[1]["funcnamehighlighting"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["gobble"] = + ListingsParam("", false, INTEGER, "", empty_hint); + all_params_[1]["highlightcolor"] = + ListingsParam("", false, ALL, "", color_hint_mint); + all_params_[1]["highlightlines"] = + ListingsParam("", false, ALL, "", _( + "A range of lines such as {1,3-4}")); + all_params_[1]["keywordcase"] = + ListingsParam("", false, ONEOF, + "lower\nupper\ncapitalize", empty_hint); + all_params_[1]["labelposition"] = + ListingsParam("", false, ONEOF, + "none\ntopline\nbottomline\nall", empty_hint); + all_params_[1]["language"] = + ListingsParam("", false, ALL, "", _( + "Enter one of the supported languages. However, if you " + "are defining a listing inset, it is better using the " + "language combo box, unless you need to enter a language not " + "offered there, otherwise the combo box will be disabled.")); + all_params_[1]["lastline"] = + ListingsParam("", false, INTEGER, "", empty_hint); + all_params_[1]["linenos"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["numberfirstline"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["numbers"] = + ListingsParam("", false, ONEOF, + "left\nright\nboth\nnone", empty_hint); + all_params_[1]["mathescape"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["numberblanklines"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["numbersep"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[1]["obeytabs"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["outencoding"] = + ListingsParam("", false, ALL, "", _( + "File encoding used by Pygments for highlighting")); + all_params_[1]["python3"] = + ListingsParam("", false, TRUEFALSE, "", _( + "Apply Python 3 highlighting")); + all_params_[1]["resetmargins"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["rulecolor"] = + ListingsParam("", false, ALL, "", color_hint_mint); + all_params_[1]["samepage"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["showspaces"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["showtabs"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["space"] = + ListingsParam("", false, ALL, "", _( + "A macro. Default: \\textvisiblespace")); + all_params_[1]["spacecolor"] = + ListingsParam("", false, ALL, "", color_hint_mint); + all_params_[1]["startinline"] = + ListingsParam("", false, TRUEFALSE, "", _("For PHP only")); + all_params_[1]["style"] = + ListingsParam("", false, ALL, "", _( + "The style used by Pygments")); + all_params_[1]["stepnumber"] = + ListingsParam("", false, INTEGER, "", empty_hint); + all_params_[1]["stepnumberfromfirst"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["stepnumberoffsetvalues"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["stripall"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["stripnl"] = + ListingsParam("", false, TRUEFALSE, "", empty_hint); + all_params_[1]["tab"] = + ListingsParam("", false, ALL, "", _( + "A macro to redefine visible tabs")); + all_params_[1]["tabcolor"] = + ListingsParam("", false, ALL, "", color_hint_mint); + all_params_[1]["tabsize"] = + ListingsParam("", false, INTEGER, "", empty_hint); + all_params_[1]["texcl"] = + ListingsParam("", false, TRUEFALSE, "", _( + "Enables latex code in comments")); + all_params_[1]["texcomments"] = + ListingsParam("", false, TRUEFALSE, "", _( + "Enables latex code in comments")); + all_params_[1]["xleftmargin"] = + ListingsParam("", false, LENGTH, "", empty_hint); + all_params_[1]["xrightmargin"] = + ListingsParam("", false, LENGTH, "", empty_hint); +} + + +docstring ParValidator::validate(string const & name, + string const & par) const +{ + int p = InsetListingsParams::package(); + + 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_[p].begin(); + ListingsParams::const_iterator end = all_params_[p].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_[p].find(name); + if (it != all_params_[p].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_[p].end(); + for (it = all_params_[p].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)); + } +} + + +bool ParValidator::onoff(string const & name) const +{ + int p = InsetListingsParams::package(); + + // locate name in parameter table + ListingsParams::const_iterator it = all_params_[p].find(name); + if (it != all_params_[p].end()) + return it->second.onoff_; + else + return false; } +} // namespace + +// define a global ParValidator +ParValidator * par_validator = 0; -InsetListingsParams::InsetListingsParams() : - inline_(false), params_(), keys_(0), status_(InsetCollapsable::Open) +// The package to be used by the global ParValidator +// (0 for listings, 1 for minted) +int InsetListingsParams::package_ = 0; + +InsetListingsParams::InsetListingsParams() + : inline_(false), params_(), status_(InsetCollapsible::Open) { } -InsetListingsParams::InsetListingsParams(string const & par, bool in, InsetCollapsable::CollapseStatus s) - : inline_(in), params_(), keys_(0), status_(s) +InsetListingsParams::InsetListingsParams(string const & par, bool in, + InsetCollapsible::CollapseStatus s) + : inline_(in), params_(), status_(s) { // this will activate parameter validation. fromEncodedString(par); @@ -469,41 +996,91 @@ void InsetListingsParams::write(ostream & os) const void InsetListingsParams::read(Lexer & lex) { lex >> inline_; - int s; + int s = InsetCollapsible::Collapsed; lex >> s; - if (lex) - status_ = static_cast(s); + status_ = static_cast(s); string par; lex >> par; fromEncodedString(par); } -void InsetListingsParams::addParam(string const & key, string const & value) -{ +string InsetListingsParams::params(string const & sep) const +{ + string par; + 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 += rtrim(it->first, "_"); + else + par += rtrim(it->first, "_") + '=' + it->second; + } + return par; +} + + +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 & val, bool replace) +{ if (key.empty()) return; - // exception may be thown. - parValidator(key.c_str()).validate(value); + + bool const is_minted_language = minted() && key == "language"; + string const value = (is_minted_language && !val.empty()) + ? languageonly(val) : val; // duplicate parameters! - if (find(keys_.begin(), keys_.end(), key) != keys_.end()) - throw invalidParam("Parameter " + key + " has already been defined"); - else - keys_.push_back(key); - if (!params_.empty()) - params_ += ','; - if (value.empty()) - params_ += 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 (!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_.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 { - // check onoff flag - size_t idx = 0; - while (listings_param_table[idx].name != key) - ++idx; - BOOST_ASSERT(listings_param_table[idx].name == key); - if (listings_param_table[idx].onoff && value == "false") - params_ += key; + bool has_special_char = false; + for (size_t i = 0; i < value.size(); ++i) + if (!isAlnumASCII(value[i])) { + has_special_char = true; + break; + } + if (has_special_char && !is_minted_language) + params_.push_back(make_pair(keyname, "{" + value + "}")); else - params_ += key + '=' + value; + params_.push_back(make_pair(keyname, value)); } } @@ -531,11 +1108,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] == ',')) - 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 @@ -549,7 +1128,6 @@ void InsetListingsParams::addParams(string const & par) void InsetListingsParams::setParams(string const & par) { params_.clear(); - keys_.clear(); addParams(par); } @@ -557,75 +1135,68 @@ void InsetListingsParams::setParams(string const & par) string InsetListingsParams::encodedString() const { // Encode string! - // FIXME: - // '"' should be handled differently because it will - // terminate a lyx token. Right now, it is silently ignored. - string par; - for (size_t i = 0; i < params_.size(); ++i) { - BOOST_ASSERT(params_[i] != '\n'); - if (params_[i] != '"') - par += params_[i]; - } + // '"' 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; } string InsetListingsParams::separatedParams(bool keepComma) const { - // , might be used as regular parameter option so - // the prcess might be more complicated than what I am doing here - string opt; - int braces = 0; - for (size_t i = 0; i < params_.size(); ++i) - if (params_[i] == ',' && braces == 0) { - if (keepComma) - opt += ",\n"; - else - opt += "\n"; - } else if (params_[i] == '{' && params_[i - 1] == '=') { - braces ++; - opt += params_[i]; - } else if (params_[i] == '}' && (i == params_.size() -1 || params_[i + 1] == ',')) { - braces --; - opt += params_[i]; - } else - opt += params_[i]; - return opt; + if (keepComma) + return params(",\n"); + else + return params("\n"); } void InsetListingsParams::fromEncodedString(string const & in) { - // Decode string! - // Do nothing because " was silently ignored. - setParams(in); + // Decode string! Reversal of encodedString + string par = in; + // '"' is now &quot; ==> '"' is now &quot; + par = subst(par, """, "\""); + // '"' is now &quot; ==> '"' is now " + par = subst(par, "&", "&"); + setParams(par); } bool InsetListingsParams::isFloat() const { - return find(keys_.begin(), keys_.end(), "float") != keys_.end(); + return hasParam("float"); } string InsetListingsParams::getParamValue(string const & param) const { - // is this parameter defined? - if (find(keys_.begin(), keys_.end(), param) == keys_.end()) - return string(); - // if so, search for it - vector pars = getVectorFromString(separatedParams(), "\n"); - for (vector::iterator it = pars.begin(); it != pars.end(); ++it) - if (prefixIs(*it, param + "=")) { - string par = it->substr(param.size() + 1); - if (prefixIs(par, "{") && suffixIs(par, "}")) - return par.substr(1, par.size() - 2); - else - return par; - } - // if param= is not found, should be something like float, return "" - return string(); + 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