Rework InsetCommandParams interface and file storage

* src/insets/insetcommandparams.[Ch]:
	(operator[]): New, access a parameter
	(clear): New, clear all parameters
	(info_): New, stire info about this command
	(cmdname): Rename to name_
	(contents, options, sec_options): Replace with params_. Parameters
	are now stored as docstring.
	(findInfo): New factor for command info for all commands
	(read, write): Use new syntax
	(parameter set and get methods): reimplemenmt for new parameter storage

	* src/insets/insetcommand.h
	(getParam): New, get a parameter
	(setParam): New, set a parameter
	(parameter set and get methods): Adjust to InsetCommandParams changes

	* src/insets/insetbibitem.[Ch]
	(write): Remove, not needed anymore
	(directWrite): ditto

	* src/insets/insetbibitem.C
	(InsetBibitem::read): Use InsetCommand::read

	* src/insets/insetref.C
	(InsetRef::latex): Use new InsetCommandParams interface

	* src/mathed/InsetMathHull.C
	(InsetMathHull::doDispatch): ditto

	* src/text3.C
	(LyXText::dispatch): ditto

	* src/factory.C
	(createInset): Create InsetCommandParams with command name
	(readInset): ditto
	(readInset): Remove error message for bibitem, since bibitem is
	now a normal command inset

	* src/buffer.C: Bump file format number

	* src/frontends/controllers/ControlCommand.[Ch]
	(ControlCommand): take an additional command name parameter

	* src/text.C
	(readParToken): Remove code for \bibitem

	* lib/lyx2lyx/LyX.py: Bump latest file format number

	* lib/lyx2lyx/lyx_1_5.py
	(convert_bibitem, convert_commandparams): new, convert to new format
	(revert_commandparams): new, convert to old format

	* development/FORMAT: document new format

	* many other files: Adjust to the changes above


git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@15357 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
Georg Baum 2006-10-17 21:07:16 +00:00
parent 4cc7a7708e
commit b02242bfaf
31 changed files with 651 additions and 167 deletions

View File

@ -1,6 +1,34 @@
LyX file-format changes
-----------------------§
2006-10-15 Georg Baum <Georg.Baum@post.rwth-aachen.de>
* format incremented to 252: changed command inset syntax
Old:
\begin_inset LatexCommand \cmdname[opt1][opt2]{arg}
preview true
\end_inset
and
\bibitem [opt1]{arg}
New:
\begin_inset LatexCommand cmdname
name1 "opt1"
name2 "opt2"
name3 "arg"
preview true
\end_inset
The order of the parameters and for each parameter the name and
optional/required bit is now stored in InsetCommandParams.
2006-10-03 Jürgen Spitzmüller <j.spitzmueller@gmx.de>
* format incremented to 251: save show_label param for charstyles.

View File

@ -73,7 +73,7 @@ format_relation = [("0_06", [200], generate_minor_versions("0.6" , 4)),
("1_2", [220], generate_minor_versions("1.2" , 4)),
("1_3", [221], generate_minor_versions("1.3" , 7)),
("1_4", range(222,246), generate_minor_versions("1.4" , 3)),
("1_5", range(246,252), generate_minor_versions("1.5" , 0))]
("1_5", range(246,253), generate_minor_versions("1.5" , 0))]
def formats_list():

View File

@ -253,6 +253,193 @@ def revert_cs_label(document):
i = i + 1
def convert_bibitem(document):
""" Convert
\bibitem [option]{argument}
to
\begin_inset LatexCommand bibitem
label "option"
key "argument"
\end_inset
This must be called after convert_commandparams.
"""
regex = re.compile(r'\S+\s*(\[[^\[\{]*\])?(\{[^}]*\})')
i = 0
while 1:
i = find_token(document.body, "\\bibitem", i)
if i == -1:
break
match = re.match(regex, document.body[i])
option = match.group(1)
argument = match.group(2)
lines = ['\\begin_inset LatexCommand bibitem']
if not option == None:
lines.append('label "%s"' % option[1:-1].replace('"', '\\"'))
lines.append('key "%s"' % argument[1:-1].replace('"', '\\"'))
lines.append('')
lines.append('\\end_inset')
document.body[i:i+1] = lines
i = i + 1
commandparams_info = {
# command : [option1, option2, argument]
"bibitem" : ["label", "", "key"],
"bibtex" : ["options", "btprint", "bibfiles"],
"cite" : ["after", "before", "key"],
"citet" : ["after", "before", "key"],
"citep" : ["after", "before", "key"],
"citealt" : ["after", "before", "key"],
"citealp" : ["after", "before", "key"],
"citeauthor" : ["after", "before", "key"],
"citeyear" : ["after", "before", "key"],
"citeyearpar" : ["after", "before", "key"],
"citet*" : ["after", "before", "key"],
"citep*" : ["after", "before", "key"],
"citealt*" : ["after", "before", "key"],
"citealp*" : ["after", "before", "key"],
"citeauthor*" : ["after", "before", "key"],
"Citet" : ["after", "before", "key"],
"Citep" : ["after", "before", "key"],
"Citealt" : ["after", "before", "key"],
"Citealp" : ["after", "before", "key"],
"Citeauthor" : ["after", "before", "key"],
"Citet*" : ["after", "before", "key"],
"Citep*" : ["after", "before", "key"],
"Citealt*" : ["after", "before", "key"],
"Citealp*" : ["after", "before", "key"],
"Citeauthor*" : ["after", "before", "key"],
"citefield" : ["after", "before", "key"],
"citetitle" : ["after", "before", "key"],
"cite*" : ["after", "before", "key"],
"hfill" : ["", "", ""],
"index" : ["", "", "name"],
"printindex" : ["", "", "name"],
"label" : ["", "", "name"],
"eqref" : ["name", "", "reference"],
"pageref" : ["name", "", "reference"],
"prettyref" : ["name", "", "reference"],
"ref" : ["name", "", "reference"],
"vpageref" : ["name", "", "reference"],
"vref" : ["name", "", "reference"],
"tableofcontents" : ["", "", "type"],
"htmlurl" : ["name", "", "target"],
"url" : ["name", "", "target"]}
def convert_commandparams(document):
""" Convert
\begin_inset LatexCommand \cmdname[opt1][opt2]{arg}
\end_inset
to
\begin_inset LatexCommand cmdname
name1 "opt1"
name2 "opt2"
name3 "arg"
\end_inset
name1, name2 and name3 can be different for each command.
"""
# \begin_inset LatexCommand bibitem was not the official version (see
# convert_bibitem()), but could be read in, so we convert it here, too.
# FIXME: Handle things like \command[foo[bar]]{foo{bar}}
# we need a real parser here.
regex = re.compile(r'\\([^\[\{]+)(\[[^\[\{]*\])?(\[[^\[\{]*\])?(\{[^}]*\})?')
i = 0
while 1:
i = find_token(document.body, "\\begin_inset LatexCommand", i)
if i == -1:
break
command = document.body[i][26:].strip()
match = re.match(regex, command)
name = match.group(1)
option1 = match.group(2)
option2 = match.group(3)
argument = match.group(4)
lines = ["\\begin_inset LatexCommand %s" % name]
if option1 != None:
if commandparams_info[name][0] == "":
document.warning("Ignoring invalid option `%s' of command `%s'." % (option1[1:-1], name))
else:
lines.append('%s "%s"' % (commandparams_info[name][0], option1[1:-1].replace('"', '\"')))
if option2 != None:
if commandparams_info[name][1] == "":
document.warning("Ignoring invalid second option `%s' of command `%s'." % (option2[1:-1], name))
else:
lines.append('%s "%s"' % (commandparams_info[name][1], option2[1:-1].replace('"', '\"')))
if argument != None:
if commandparams_info[name][2] == "":
document.warning("Ignoring invalid argument `%s' of command `%s'." % (argument[1:-1], name))
else:
lines.append('%s "%s"' % (commandparams_info[name][2], argument[1:-1].replace('"', '\"')))
document.body[i:i+1] = lines
i = i + 1
def revert_commandparams(document):
regex = re.compile(r'(\S+)\s+(.+)')
i = 0
while 1:
i = find_token(document.body, "\\begin_inset LatexCommand", i)
if i == -1:
break
name = document.body[i].split()[2]
j = find_end_of_inset(document.body, i + 1)
preview_line = ""
option1 = ""
option2 = ""
argument = ""
for k in range(i + 1, j):
match = re.match(regex, document.body[k])
if match:
pname = match.group(1)
pvalue = match.group(2)
if pname == "preview":
preview_line = document.body[k]
elif (commandparams_info[name][0] != "" and
pname == commandparams_info[name][0]):
option1 = pvalue.strip('"').replace('\\"', '"')
elif (commandparams_info[name][1] != "" and
pname == commandparams_info[name][1]):
option2 = pvalue.strip('"').replace('\\"', '"')
elif (commandparams_info[name][2] != "" and
pname == commandparams_info[name][2]):
argument = pvalue.strip('"').replace('\\"', '"')
elif document.body[k].strip() != "":
document.warning("Ignoring unknown contents `%s' in command inset %s." % (document.body[k], name))
if name == "bibitem":
if option1 == "":
lines = ["\\bibitem {%s}" % argument]
else:
lines = ["\\bibitem [%s]{%s}" % (option1, argument)]
else:
if option1 == "":
if option2 == "":
lines = ["\\begin_inset LatexCommand \\%s{%s}" % (name, argument)]
else:
lines = ["\\begin_inset LatexCommand \\%s[][%s]{%s}" % (name, option2, argument)]
else:
if option2 == "":
lines = ["\\begin_inset LatexCommand \\%s[%s]{%s}" % (name, option1, argument)]
else:
lines = ["\\begin_inset LatexCommand \\%s[%s][%s]{%s}" % (name, option1, option2, argument)]
if name != "bibitem":
if preview_line != "":
lines.append(preview_line)
lines.append('')
lines.append('\\end_inset')
document.body[i:j+1] = lines
i = j + 1
##
# Conversion hub
#
@ -263,9 +450,11 @@ convert = [[246, []],
[248, []],
[249, [convert_utf8]],
[250, []],
[251, []]]
[251, []],
[252, [convert_commandparams, convert_bibitem]]]
revert = [[250, [revert_cs_label]],
revert = [[251, [revert_commandparams]],
[250, [revert_cs_label]],
[249, []],
[248, [revert_utf8]],
[247, [revert_booktabs]],

View File

@ -137,6 +137,7 @@ src/frontends/qt4/QBranch.C
src/frontends/qt4/QBranches.C
src/frontends/qt4/QChanges.C
src/frontends/qt4/QCharacter.C
src/frontends/qt4/QCitationDialog.C
src/frontends/qt4/QCommandBuffer.C
src/frontends/qt4/QDelimiterDialog.C
src/frontends/qt4/QDocument.C
@ -163,6 +164,7 @@ src/frontends/qt4/QTabular.C
src/frontends/qt4/QTabularCreate.C
src/frontends/qt4/QTexinfo.C
src/frontends/qt4/QThesaurus.C
src/frontends/qt4/QTocDialog.C
src/frontends/qt4/QVSpace.C
src/frontends/qt4/QWrap.C
src/frontends/qt4/Qt2BC.h

View File

@ -144,7 +144,7 @@ using std::string;
namespace {
int const LYX_FORMAT = 251;
int const LYX_FORMAT = 252;
} // namespace anon

View File

@ -211,19 +211,19 @@ InsetBase * createInset(BufferView * bv, FuncRequest const & cmd)
string const name = cmd.getArg(0);
if (name == "bibitem") {
InsetCommandParams icp;
InsetCommandParams icp(name);
InsetCommandMailer::string2params(name, lyx::to_utf8(cmd.argument()),
icp);
return new InsetBibitem(icp);
} else if (name == "bibtex") {
InsetCommandParams icp;
InsetCommandParams icp(name);
InsetCommandMailer::string2params(name, lyx::to_utf8(cmd.argument()),
icp);
return new InsetBibtex(icp);
} else if (name == "citation") {
InsetCommandParams icp;
InsetCommandParams icp("cite");
InsetCommandMailer::string2params(name, lyx::to_utf8(cmd.argument()),
icp);
return new InsetCitation(icp);
@ -252,36 +252,36 @@ InsetBase * createInset(BufferView * bv, FuncRequest const & cmd)
return inset.release();
} else if (name == "include") {
InsetCommandParams iip;
InsetCommandParams iip(name);
InsetIncludeMailer::string2params(lyx::to_utf8(cmd.argument()), iip);
return new InsetInclude(iip);
} else if (name == "index") {
InsetCommandParams icp;
InsetCommandParams icp(name);
InsetCommandMailer::string2params(name, lyx::to_utf8(cmd.argument()),
icp);
return new InsetIndex(icp);
} else if (name == "label") {
InsetCommandParams icp;
InsetCommandParams icp(name);
InsetCommandMailer::string2params(name, lyx::to_utf8(cmd.argument()),
icp);
return new InsetLabel(icp);
} else if (name == "ref") {
InsetCommandParams icp;
InsetCommandParams icp(name);
InsetCommandMailer::string2params(name, lyx::to_utf8(cmd.argument()),
icp);
return new InsetRef(icp, *bv->buffer());
} else if (name == "toc") {
InsetCommandParams icp;
InsetCommandParams icp("tableofcontents");
InsetCommandMailer::string2params(name, lyx::to_utf8(cmd.argument()),
icp);
return new InsetTOC(icp);
} else if (name == "url") {
InsetCommandParams icp;
InsetCommandParams icp(name);
InsetCommandMailer::string2params(name, lyx::to_utf8(cmd.argument()),
icp);
return new InsetUrl(icp);
@ -344,10 +344,12 @@ InsetBase * readInset(LyXLex & lex, Buffer const & buf)
// test the different insets
if (tmptok == "LatexCommand") {
InsetCommandParams inscmd;
inscmd.read(lex);
lex.next();
string const cmdName = lex.getString();
lex.pushToken(cmdName);
string const cmdName = inscmd.getCmdName();
InsetCommandParams inscmd(cmdName);
inscmd.read(lex);
// This strange command allows LyX to recognize "natbib" style
// citations: citet, citep, Citet etc.
@ -360,7 +362,6 @@ InsetBase * readInset(LyXLex & lex, Buffer const & buf)
if (compare_ascii_no_case(cmdName.substr(0,4), "cite") == 0) {
inset.reset(new InsetCitation(inscmd));
} else if (cmdName == "bibitem") {
lex.printError("Wrong place for bibitem");
inset.reset(new InsetBibitem(inscmd));
} else if (cmdName == "bibtex") {
inset.reset(new InsetBibtex(inscmd));

View File

@ -44,7 +44,7 @@ namespace frontend {
ControlBibtex::ControlBibtex(Dialog & d)
: ControlCommand(d, "bibtex")
: ControlCommand(d, "bibtex", "bibtex")
{}

View File

@ -28,7 +28,7 @@ vector<biblio::CiteStyle> ControlCitation::citeStyles_;
ControlCitation::ControlCitation(Dialog & d)
: ControlCommand(d, "citation")
: ControlCommand(d, "cite", "citation")
{}

View File

@ -21,8 +21,9 @@ using std::string;
namespace lyx {
namespace frontend {
ControlCommand::ControlCommand(Dialog & dialog, string const & lfun_name)
: Dialog::Controller(dialog),
ControlCommand::ControlCommand(Dialog & dialog, string const & command_name,
string const & lfun_name)
: Dialog::Controller(dialog), params_(command_name),
lfun_name_(lfun_name)
{}
@ -38,7 +39,7 @@ bool ControlCommand::initialiseParams(string const & data)
void ControlCommand::clearParams()
{
params_ = InsetCommandParams();
params_.clear();
}

View File

@ -26,9 +26,11 @@ class ControlCommand : public Dialog::Controller {
public:
/** LFUN_INSET_APPLY requires a name, "citation", "ref" etc so that
it knows what to do with the rest of the contents.
An empty name indicates that no action will occur on 'Apply'.
An empty \p lfun_name indicates that no action will occur on
'Apply'.
*/
ControlCommand(Dialog &, std::string const & lfun_name = std::string());
ControlCommand(Dialog &, std::string const & command_name,
std::string const & lfun_name);
///
InsetCommandParams & params() { return params_; }
///

View File

@ -42,7 +42,7 @@ using support::onlyPath;
namespace frontend {
ControlInclude::ControlInclude(Dialog & parent)
: Dialog::Controller(parent)
: Dialog::Controller(parent), params_("include")
{}
@ -55,7 +55,7 @@ bool ControlInclude::initialiseParams(string const & data)
void ControlInclude::clearParams()
{
params_ = InsetCommandParams();
params_.clear();
}

View File

@ -32,7 +32,7 @@ using support::makeDisplayPath;
namespace frontend {
ControlRef::ControlRef(Dialog & d)
: ControlCommand(d, "ref")
: ControlCommand(d, "ref", "ref")
{}

View File

@ -29,7 +29,7 @@ namespace frontend {
ControlToc::ControlToc(Dialog & d)
: ControlCommand(d, "toc")
: ControlCommand(d, "tableofcontents", "toc")
{}

View File

@ -185,7 +185,7 @@ Dialogs::DialogPtr Dialogs::build(string const & name)
dialog->bc().bp(new OkCancelPolicy);
} else if (name == "bibitem") {
dialog->bc().view(new GBC(dialog->bc()));
dialog->setController(new ControlCommand(*dialog, name));
dialog->setController(new ControlCommand(*dialog, name, name));
dialog->setView(new GBibItem(*dialog));
dialog->bc().bp(new OkCancelReadOnlyPolicy);
} else if (name == "bibtex") {
@ -260,7 +260,7 @@ Dialogs::DialogPtr Dialogs::build(string const & name)
dialog->bc().bp(new OkApplyCancelReadOnlyPolicy);
} else if (name == "index") {
dialog->bc().view(new GBC(dialog->bc()));
dialog->setController(new ControlCommand(*dialog, name));
dialog->setController(new ControlCommand(*dialog, name, name));
// FIXME UNICODE
dialog->setView(new GText(*dialog,
lyx::to_utf8(_("Index Entry")),
@ -268,7 +268,7 @@ Dialogs::DialogPtr Dialogs::build(string const & name)
dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
} else if (name == "label") {
dialog->bc().view(new GBC(dialog->bc()));
dialog->setController(new ControlCommand(*dialog, name));
dialog->setController(new ControlCommand(*dialog, name, name));
// FIXME UNICODE
dialog->setView(new GText(*dialog,
lyx::to_utf8(_("Label")),
@ -548,7 +548,7 @@ Dialogs::DialogPtr Dialogs::build(string const & name)
dialog->bc().bp(new OkCancelPolicy);
} else if (name == "url") {
dialog->bc().view(new GBC(dialog->bc()));
dialog->setController(new ControlCommand(*dialog, name));
dialog->setController(new ControlCommand(*dialog, name, name));
dialog->setView(new GUrl(*dialog));
dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
} else if (name == "vspace") {

View File

@ -150,7 +150,7 @@ Dialogs::DialogPtr Dialogs::build(string const & name)
dialog->setView(new QAbout(*dialog));
dialog->bc().bp(new OkCancelPolicy);
} else if (name == "bibitem") {
dialog->setController(new ControlCommand(*dialog, name));
dialog->setController(new ControlCommand(*dialog, name, name));
dialog->setView(new QBibitem(*dialog));
dialog->bc().bp(new OkCancelReadOnlyPolicy);
} else if (name == "bibtex") {
@ -214,13 +214,13 @@ Dialogs::DialogPtr Dialogs::build(string const & name)
dialog->setView(new QInclude(*dialog));
dialog->bc().bp(new OkApplyCancelReadOnlyPolicy);
} else if (name == "index") {
dialog->setController(new ControlCommand(*dialog, name));
dialog->setController(new ControlCommand(*dialog, name, name));
dialog->setView(new QIndex(*dialog,
_("Index Entry"),
qt_("&Keyword:")));
dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
} else if (name == "label") {
dialog->setController(new ControlCommand(*dialog, name));
dialog->setController(new ControlCommand(*dialog, name, name));
dialog->setView(new QIndex(*dialog,
_("Label"),
qt_("&Label:")));
@ -296,7 +296,7 @@ Dialogs::DialogPtr Dialogs::build(string const & name)
dialog->setView(new QToc(*dialog));
dialog->bc().bp(new OkCancelPolicy);
} else if (name == "url") {
dialog->setController(new ControlCommand(*dialog, name));
dialog->setController(new ControlCommand(*dialog, name, name));
dialog->setView(new QURL(*dialog));
dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
} else if (name == "vspace") {

View File

@ -146,7 +146,7 @@ Dialogs::DialogPtr Dialogs::build(string const & name)
dialog->setView(new QAbout(*dialog));
dialog->bc().bp(new OkCancelPolicy);
} else if (name == "bibitem") {
dialog->setController(new ControlCommand(*dialog, name));
dialog->setController(new ControlCommand(*dialog, name, name));
dialog->setView(new QBibitem(*dialog));
dialog->bc().bp(new OkCancelReadOnlyPolicy);
} else if (name == "bibtex") {
@ -211,13 +211,13 @@ Dialogs::DialogPtr Dialogs::build(string const & name)
dialog->setView(new QInclude(*dialog));
dialog->bc().bp(new OkApplyCancelReadOnlyPolicy);
} else if (name == "index") {
dialog->setController(new ControlCommand(*dialog, name));
dialog->setController(new ControlCommand(*dialog, name, name));
dialog->setView(new QIndex(*dialog,
_("Index Entry"),
qt_("&Keyword:")));
dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
} else if (name == "label") {
dialog->setController(new ControlCommand(*dialog, name));
dialog->setController(new ControlCommand(*dialog, name, name));
dialog->setView(new QIndex(*dialog,
_("Label"),
qt_("&Label:")));
@ -295,7 +295,7 @@ Dialogs::DialogPtr Dialogs::build(string const & name)
dialog->setView(new QTocDialog(*dialog, qtoc));
dialog->bc().bp(new OkCancelPolicy);
} else if (name == "url") {
dialog->setController(new ControlCommand(*dialog, name));
dialog->setController(new ControlCommand(*dialog, name, name));
dialog->setView(new UrlView(*dialog));
dialog->bc().bp(new NoRepeatedApplyReadOnlyPolicy);
} else if (name == "vspace") {

View File

@ -57,7 +57,7 @@ void InsetBibitem::doDispatch(LCursor & cur, FuncRequest & cmd)
switch (cmd.action) {
case LFUN_INSET_MODIFY: {
InsetCommandParams p;
InsetCommandParams p("bibitem");
InsetCommandMailer::string2params("bibitem", lyx::to_utf8(cmd.argument()), p);
if (p.getCmdName().empty()) {
cur.noUpdate();
@ -82,27 +82,9 @@ void InsetBibitem::setCounter(int c)
}
// I'm sorry but this is still necessary because \bibitem is used also
// as a LyX 2.x command, and lyxlex is not enough smart to understand
// real LaTeX commands. Yes, that could be fixed, but would be a waste
// of time cause LyX3 won't use lyxlex anyway. (ale)
void InsetBibitem::write(Buffer const &, std::ostream & os) const
void InsetBibitem::read(Buffer const & buf, LyXLex & lex)
{
os << "\n\\bibitem ";
if (!getOptions().empty())
os << '[' << getOptions() << ']';
os << '{' << getContents() << "}\n";
}
// This is necessary here because this is written without begin_inset
// This should be changed!!! (Jug)
void InsetBibitem::read(Buffer const &, LyXLex & lex)
{
if (lex.eatLine())
scanCommand(lex.getString());
else
lex.printError("InsetCommand: Parse error: `$$Token'");
InsetCommand::read(buf, lex);
if (prefixIs(getContents(), key_prefix)) {
int const key = convert<int>(getContents().substr(key_prefix.length()));

View File

@ -24,10 +24,6 @@ class InsetBibitem : public InsetCommand {
public:
///
InsetBibitem(InsetCommandParams const &);
/** Currently \bibitem is used as a LyX2.x command,
so we need this method.
*/
void write(Buffer const &, std::ostream &) const;
///
void read(Buffer const &, LyXLex & lex);
///
@ -36,8 +32,6 @@ public:
EDITABLE editable() const { return IS_EDITABLE; }
///
InsetBase::Code lyxCode() const { return InsetBase::BIBITEM_CODE; }
/// keep .lyx format compatible
bool directWrite() const { return true; }
///
void setCounter(int);
///

View File

@ -86,7 +86,7 @@ void InsetBibtex::doDispatch(LCursor & cur, FuncRequest & cmd)
switch (cmd.action) {
case LFUN_INSET_MODIFY: {
InsetCommandParams p;
InsetCommandParams p("bibtex");
InsetCommandMailer::string2params("bibtex", lyx::to_utf8(cmd.argument()), p);
if (!p.getCmdName().empty()) {
setParams(p);

View File

@ -58,7 +58,7 @@ private:
class Cache {
public:
///
Cache() : engine(lyx::biblio::ENGINE_BASIC) {}
Cache() : engine(lyx::biblio::ENGINE_BASIC), params("cite") {}
///
lyx::biblio::CiteEngine engine;
///

View File

@ -31,7 +31,7 @@ using std::ostringstream;
InsetCommand::InsetCommand(InsetCommandParams const & p,
string const & mailer_name)
: p_(p.getCmdName(), p.getContents(), p.getOptions(), p.getSecOptions()),
: p_(p),
mailer_name_(mailer_name),
updateButtonLabel_(true)
{}
@ -100,7 +100,7 @@ void InsetCommand::doDispatch(LCursor & cur, FuncRequest & cmd)
break;
case LFUN_INSET_MODIFY: {
InsetCommandParams p;
InsetCommandParams p(p_.getCmdName());
InsetCommandMailer::string2params(mailer_name_, lyx::to_utf8(cmd.argument()), p);
if (p.getCmdName().empty())
cur.noUpdate();
@ -172,7 +172,7 @@ void InsetCommandMailer::string2params(string const & name,
string const & in,
InsetCommandParams & params)
{
params = InsetCommandParams();
params.clear();
if (in.empty())
return;

View File

@ -45,6 +45,7 @@ public:
virtual void read(Buffer const &, LyXLex & lex)
{ p_.read(lex); }
/// Can remove one InsetBibKey is modified
/// FIXME remove
void scanCommand(std::string const & c) { p_.scanCommand(c); };
///
virtual int latex(Buffer const &, std::ostream &,
@ -60,20 +61,31 @@ public:
///
InsetCommandParams const & params() const { return p_; }
///
std::string const & getContents() const { return p_.getContents(); }
///
/// FIXME remove
std::string const getContents() const { return p_.getContents(); }
/// FIXME remove
void setContents(std::string const & c)
{
updateButtonLabel_ = true;
p_.setContents(c);
}
///
void setParam(std::string const & name, lyx::docstring const & value)
{
updateButtonLabel_ = true;
p_[name] = value;
}
///
lyx::docstring const & getParam(std::string const & name) const
{
return p_[name];
}
/// FIXME remove
virtual void replaceContents(std::string const & from, std::string const & to);
///
std::string const & getOptions() const { return p_.getOptions(); }
///
std::string const & getSecOptions() const { return p_.getSecOptions(); }
/// FIXME remove
std::string const getOptions() const { return p_.getOptions(); }
/// FIXME remove
std::string const getSecOptions() const { return p_.getSecOptions(); }
///
RenderButton & button() const { return button_; }

View File

@ -4,6 +4,7 @@
* Licence details can be found in the file COPYING.
*
* \author Angus Leeming
* \author Georg Baum
*
* Full author contact details are available in file CREDITS.
*/
@ -15,23 +16,152 @@
#include "debug.h"
#include "lyxlex.h"
#include "support/lstrings.h"
#include <boost/assert.hpp>
using lyx::docstring;
using lyx::support::findToken;
using std::string;
using std::endl;
using std::ostream;
InsetCommandParams::InsetCommandParams()
{}
InsetCommandParams::InsetCommandParams(string const & name)
: name_(name), preview_(false)
{
info_ = findInfo(name);
BOOST_ASSERT(info_);
params_.resize(info_->n);
}
InsetCommandParams::InsetCommandParams(string const & n,
string const & c,
string const & o,
string const & s)
: cmdname(n), contents(c), options(o), sec_options(s),
preview_(false)
{}
InsetCommandParams::CommandInfo const *
InsetCommandParams::findInfo(std::string const & name)
{
// No parameter may be named "preview", because that is a required
// flag for all commands.
// InsetBibitem
if (name == "bibitem") {
static const char * const paramnames[] = {"label", "key", ""};
static const bool isoptional[] = {true, false};
static const CommandInfo info = {2, paramnames, isoptional};
return &info;
}
// InsetBibtex
if (name == "bibtex") {
static const char * const paramnames[] =
{"options", "btprint", "bibfiles", ""};
static const bool isoptional[] = {true, true, false};
static const CommandInfo info = {3, paramnames, isoptional};
return &info;
}
// InsetCitation
// FIXME: Use is_possible_cite_command() in
// src/frontends/controllers/biblio.C, see comment in src/factory.C.
if (name == "cite" || name == "citet" || name == "citep" || name == "citealt" ||
name == "citealp" || name == "citeauthor" || name == "citeyear" ||
name == "citeyearpar" || name == "citet*" || name == "citep*" ||
name == "citealt*" || name == "citealp*" ||
name == "citeauthor*" || name == "Citet" || name == "Citep" ||
name == "Citealt" || name == "Citealp" || name == "Citeauthor" ||
name == "Citet*" || name == "Citep*" || name == "Citealt*" ||
name == "Citealp*" || name == "Citeauthor*" ||
name == "citefield" || name == "citetitle" || name == "cite*") {
// 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;
}
// InsetFloatlist
if (name == "floatlist") {
static const char * const paramnames[] = {"type", ""};
static const bool isoptional[] = {false};
static const CommandInfo info = {1, paramnames, isoptional};
return &info;
}
// InsetHfill
if (name == "hfill") {
static const char * const paramnames[] = {""};
static const CommandInfo info = {0, paramnames, 0};
return &info;
}
// InsetInclude
if (name == "include" || name == "input" || name == "verbatiminput" ||
name == "verbatiminput*") {
static const char * const paramnames[] = {"filename", ""};
static const bool isoptional[] = {false};
static const CommandInfo info = {1, paramnames, isoptional};
return &info;
}
// InsetIndex, InsetPrintIndex, InsetLabel
if (name == "index" || name == "printindex" || name == "label") {
static const char * const paramnames[] = {"name", ""};
static const bool isoptional[] = {false};
static const CommandInfo info = {1, paramnames, isoptional};
return &info;
}
// InsetRef
if (name == "eqref" || name == "pageref" || name == "vpageref" ||
name == "vref" || name == "prettyref" || name == "ref") {
static const char * const paramnames[] =
{"name", "reference", ""};
static const bool isoptional[] = {true, false};
static const CommandInfo info = {2, paramnames, isoptional};
return &info;
}
// InsetTOC
if (name == "tableofcontents") {
static const char * const paramnames[] = {"type", ""};
static const bool isoptional[] = {false};
static const CommandInfo info = {1, paramnames, isoptional};
return &info;
}
// InsetUrl
if (name == "htmlurl" || name == "url") {
static const char * const paramnames[] =
{"name", "target", ""};
static const bool isoptional[] = {true, false};
static const CommandInfo info = {2, paramnames, isoptional};
return &info;
}
return 0;
}
void InsetCommandParams::setCmdName(string const & name)
{
name_ = name;
CommandInfo const * const info = findInfo(name);
BOOST_ASSERT(info);
ParamVector params(info->n);
// Overtake parameters with the same name
for (size_t i = 0; i < info_->n; ++i) {
int j = findToken(info->paramnames, info_->paramnames[i]);
if (j >= 0)
params[j] = params_[i];
}
info_ = info;
std::swap(params, params_);
}
void InsetCommandParams::scanCommand(string const & cmd)
@ -108,24 +238,32 @@ void InsetCommandParams::scanCommand(string const & cmd)
void InsetCommandParams::read(LyXLex & lex)
{
string token;
if (lex.eatLine()) {
token = lex.getString();
scanCommand(token);
} else {
lex.printError("InsetCommand: Parse error: `$$Token'");
if (lex.isOK()) {
lex.next();
name_ = lex.getString();
info_ = findInfo(name_);
if (!info_)
lex.printError("InsetCommand: Unknown inset name `$$Token'");
}
string token;
while (lex.isOK()) {
lex.next();
token = lex.getString();
if (token == "\\end_inset")
break;
// FIXME Why is preview_ read but not written?
if (token == "preview") {
lex.next();
preview_ = lex.getBool();
continue;
}
int const i = findToken(info_->paramnames, token);
if (i >= 0) {
lex.next(true);
params_[i] = lex.getDocString();
} else
lex.printError("Unknown parameter name `$$Token' for command " + name_);
}
if (token != "\\end_inset") {
lex.printError("Missing \\end_inset at this point. "
@ -136,33 +274,151 @@ void InsetCommandParams::read(LyXLex & lex)
void InsetCommandParams::write(ostream & os) const
{
os << "LatexCommand " << getCommand() << "\n";
os << "LatexCommand " << name_ << '\n';
for (size_t i = 0; i < info_->n; ++i)
if (!params_[i].empty())
// FIXME UNICODE
os << info_->paramnames[i] << ' '
<< LyXLex::quoteString(lyx::to_utf8(params_[i]))
<< '\n';
}
string const InsetCommandParams::getCommand() const
{
string s;
if (!getCmdName().empty()) s += '\\' + getCmdName();
if (!getOptions().empty()) s += '[' + getOptions() + ']';
if (!getSecOptions().empty()) {
// for cases like \command[][sec_option]{arg}
if (getOptions().empty()) s += "[]";
s += '[' + getSecOptions() + ']';
docstring s = '\\' + lyx::from_ascii(name_);
for (size_t i = 0; i < info_->n; ++i) {
if (info_->optional[i]) {
if (params_[i].empty()) {
// We need to write this parameter even if
// it is empty if nonempty optional parameters
// follow before the next required parameter.
for (size_t j = i + 1; j < info_->n; ++j) {
if (!info_->optional[j])
break;
if (!params_[j].empty()) {
s += "[]";
break;
}
}
} else
s += '[' + params_[i] + ']';
} else
s += '{' + params_[i] + '}';
}
s += '{' + getContents() + '}';
return s;
return lyx::to_utf8(s);
}
std::string const InsetCommandParams::getOptions() const
{
for (size_t i = 0; i < info_->n; ++i)
if (info_->optional[i])
return lyx::to_utf8(params_[i]);
lyxerr << "Programming error: get nonexisting option in "
<< name_ << " 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 lyx::to_utf8(params_[i]);
}
// Happens in InsetCitation
lyxerr << "Programming error: get nonexisting second option in "
<< name_ << " inset." << endl;;
return string();
}
std::string const InsetCommandParams::getContents() const
{
for (size_t i = 0; i < info_->n; ++i)
if (!info_->optional[i])
return lyx::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] = lyx::from_utf8(o);
return;
}
lyxerr << "Programming error: set nonexisting option in "
<< name_ << " 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] = lyx::from_utf8(s);
return;
}
}
// Happens in InsetCitation
lyxerr << "Programming error: set nonexisting second option in "
<< name_ << " inset." << endl;;
}
void InsetCommandParams::setContents(std::string const & c)
{
for (size_t i = 0; i < info_->n; ++i)
if (!info_->optional[i]) {
params_[i] = lyx::from_utf8(c);
return;
}
BOOST_ASSERT(false);
}
docstring const & InsetCommandParams::operator[](string const & name) const
{
int const i = findToken(info_->paramnames, name);
BOOST_ASSERT(i >= 0);
return params_[i];
}
docstring & InsetCommandParams::operator[](string const & name)
{
int const i = findToken(info_->paramnames, name);
BOOST_ASSERT(i >= 0);
return params_[i];
}
void InsetCommandParams::clear()
{
for (size_t i = 0; i < info_->n; ++i)
params_[i].clear();
}
bool operator==(InsetCommandParams const & o1,
InsetCommandParams const & o2)
{
return o1.getCmdName() == o2.getCmdName()
&& o1.getContents() == o2.getContents()
&& o1.getOptions() == o2.getOptions()
&& o1.getSecOptions() == o2.getSecOptions()
&& o1.preview() == o2.preview();
return o1.name_ == o2.name_ &&
o1.info_ == o2.info_ &&
o1.params_ == o2.params_ &&
o1.preview_ == o2.preview_;
}

View File

@ -5,6 +5,7 @@
* Licence details can be found in the file COPYING.
*
* \author Angus Leeming
* \author Georg Baum
*
* Full author contact details are available in file CREDITS.
*/
@ -12,8 +13,10 @@
#ifndef INSETCOMMANDPARAMS_H
#define INSETCOMMANDPARAMS_H
#include <string>
#include "support/docstring.h"
#include <iosfwd>
#include <vector>
class LyXLex;
@ -21,53 +24,74 @@ class LyXLex;
class InsetCommandParams {
public:
///
InsetCommandParams();
///
explicit InsetCommandParams(std::string const & n,
std::string const & c = std::string(),
std::string const & o = std::string(),
std::string const & s = std::string());
/// Construct parameters for command \p name. \p name must be known.
explicit InsetCommandParams(std::string const & name);
///
void read(LyXLex &);
/// Parse the command
/// FIXME remove
void scanCommand(std::string const &);
///
void write(std::ostream &) const;
/// Build the complete LaTeX command
std::string const getCommand() const;
///
std::string const & getCmdName() const { return cmdname; }
///
std::string const & getOptions() const { return options; }
///
std::string const & getSecOptions() const { return sec_options; }
///
std::string const & getContents() const { return contents; }
///
void setCmdName(std::string const & n) { cmdname = n; }
///
void setOptions(std::string const & o) { options = o; }
///
void setSecOptions(std::string const & s) { sec_options = s; }
///
void setContents(std::string const & c) { contents = c; }
/// Return the command name
std::string const & getCmdName() const { return name_; }
/// FIXME remove
std::string const getOptions() const;
/// FIXME remove
std::string const getSecOptions() const;
/// FIXME remove
std::string const getContents() const;
/// Set the name to \p n. This must be a known name. All parameters
/// are cleared except those that exist also in the new command.
/// What matters here is the parameter name, not position.
void setCmdName(std::string const & n);
/// FIXME remove
void setOptions(std::string const &);
/// FIXME remove
void setSecOptions(std::string const &);
/// FIXME remove
void setContents(std::string const &);
/// get parameter \p name
lyx::docstring const & operator[](std::string const & name) const;
/// set parameter \p name
lyx::docstring & operator[](std::string const & name);
///
bool preview() const { return preview_; }
///
void preview(bool p) { preview_ = p; }
/// Clear the values of all parameters
void clear();
private:
///
std::string cmdname;
struct CommandInfo {
/// Number of parameters
size_t n;
/// Parameter names. paramnames[n] must be "".
char const * const * paramnames;
/// Tells whether a parameter is optional
bool const * optional;
};
/// Get information for command \p name.
/// Returns 0 if the command is not known.
static CommandInfo const * findInfo(std::string const & name);
/// Description of all command properties
CommandInfo const * info_;
/// The name of this command as it appears in .lyx and .tex files
std::string name_;
///
std::string contents;
///
std::string options;
///
std::string sec_options;
typedef std::vector<lyx::docstring> ParamVector;
/// The parameters (both optional and required ones). The order is
/// the same that is required for LaTeX output. The size of params_
/// is always info_->n.
ParamVector params_;
///
bool preview_;
///
friend bool operator==(InsetCommandParams const &,
InsetCommandParams const &);
};

View File

@ -36,12 +36,12 @@ using std::ostream;
InsetFloatList::InsetFloatList()
: InsetCommand(InsetCommandParams(), "toc")
: InsetCommand(InsetCommandParams("floatlist"), "toc")
{}
InsetFloatList::InsetFloatList(string const & type)
: InsetCommand(InsetCommandParams(), "toc")
: InsetCommand(InsetCommandParams("floatlist"), "toc")
{
setCmdName(type);
}

View File

@ -126,7 +126,7 @@ void InsetInclude::doDispatch(LCursor & cur, FuncRequest & cmd)
switch (cmd.action) {
case LFUN_INSET_MODIFY: {
InsetCommandParams p;
InsetCommandParams p("include");
InsetIncludeMailer::string2params(lyx::to_utf8(cmd.argument()), p);
if (!p.getCmdName().empty()) {
set(p, cur.buffer());
@ -761,7 +761,7 @@ string const InsetIncludeMailer::inset2string(Buffer const &) const
void InsetIncludeMailer::string2params(string const & in,
InsetCommandParams & params)
{
params = InsetCommandParams();
params.clear();
if (in.empty())
return;

View File

@ -64,7 +64,7 @@ void InsetLabel::doDispatch(LCursor & cur, FuncRequest & cmd)
switch (cmd.action) {
case LFUN_INSET_MODIFY: {
InsetCommandParams p;
InsetCommandParams p("label");
InsetCommandMailer::string2params("label", lyx::to_utf8(cmd.argument()), p);
if (p.getCmdName().empty()) {
cur.noUpdate();

View File

@ -87,12 +87,10 @@ docstring const InsetRef::getScreenLabel(Buffer const &) const
int InsetRef::latex(Buffer const &, ostream & os,
OutputParams const &) const
{
if (getOptions().empty())
os << escape(getCommand());
else {
InsetCommandParams p(getCmdName(), getContents(), "");
os << escape(p.getCommand());
}
// Don't output p_["name"], this is only used in docbook
InsetCommandParams p(getCmdName());
p["reference"] = getParam("reference");
os << escape(p.getCommand());
return 0;
}

View File

@ -1089,15 +1089,14 @@ void InsetMathHull::doDispatch(LCursor & cur, FuncRequest & cmd)
case LFUN_LABEL_INSERT: {
recordUndoInset(cur);
row_type r = (type_ == hullMultline) ? nrows() - 1 : cur.row();
string old_label = label(r);
string const default_label =
(lyxrc.label_init_length >= 0) ? "eq:" : "";
docstring old_label = lyx::from_utf8(label(r));
docstring const default_label = lyx::from_ascii(
(lyxrc.label_init_length >= 0) ? "eq:" : "");
if (old_label.empty())
old_label = default_label;
string const contents = cmd.argument().empty() ?
old_label : lyx::to_utf8(cmd.argument());
InsetCommandParams p("label", contents);
InsetCommandParams p("label");
p["name"] = cmd.argument().empty() ? old_label : cmd.argument();
string const data = InsetCommandMailer::params2string("label", p);
if (cmd.argument().empty())
@ -1113,7 +1112,7 @@ void InsetMathHull::doDispatch(LCursor & cur, FuncRequest & cmd)
//lyxerr << "arg: " << lyx::to_utf8(cmd.argument()) << endl;
string const name = cmd.getArg(0);
if (name == "label") {
InsetCommandParams p;
InsetCommandParams p("label");
InsetCommandMailer::string2params(name, lyx::to_utf8(cmd.argument()), p);
string str = p.getContents();
recordUndoInset(cur);

View File

@ -314,11 +314,6 @@ void readParToken(Buffer const & buf, Paragraph & par, LyXLex & lex,
auto_ptr<InsetBase> inset(new InsetTabular(buf));
inset->read(buf, lex);
par.insertInset(par.size(), inset.release(), font, change);
} else if (token == "\\bibitem") {
InsetCommandParams p("bibitem", "dummy");
auto_ptr<InsetBibitem> inset(new InsetBibitem(p));
inset->read(buf, lex);
par.insertInset(par.size(), inset.release(), font, change);
} else if (token == "\\hfill") {
par.insertInset(par.size(), new InsetHFill, font, change);
} else if (token == "\\lyxline") {

View File

@ -1099,11 +1099,12 @@ void LyXText::dispatch(LCursor & cur, FuncRequest & cmd)
}
case LFUN_LABEL_INSERT: {
InsetCommandParams p("label");
// Try to generate a valid label
string const contents = cmd.argument().empty() ?
cur.getPossibleLabel() : lyx::to_utf8(cmd.argument());
InsetCommandParams p("label", contents);
p["name"] = (cmd.argument().empty()) ?
// FIXME UNICODE
lyx::from_utf8(cur.getPossibleLabel()) :
cmd.argument();
string const data = InsetCommandMailer::params2string("label", p);
if (cmd.argument().empty()) {