mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-10 20:04:46 +00:00
handle natbib and jurabib packages and citation commands
git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@8882 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
ff5a462b35
commit
cfed2612eb
@ -1,3 +1,18 @@
|
||||
2004-08-10 Georg Baum <Georg.Baum@post.rwth-aachen.de>
|
||||
|
||||
* preamble.C (split_options): new, split package options into vector
|
||||
* preamble.C (add_package): new, add a package with options to
|
||||
used_packages
|
||||
* preamble.C, tex2lyx.h (used_packages): new map of used packages
|
||||
and options
|
||||
* preamble.C (handle_package): handle natbib and jurabib package
|
||||
* preamble.C (handle_package): output a message for unhandled options
|
||||
* preamble.C (parse_preamble): handle \jurabibsetup
|
||||
* text.C (known_natbib_commands): new list of known natbib ccommands
|
||||
* text.C (known_jurabib_commands): new list of known jurabib ccommands
|
||||
* text.C (getCiteArguments): new, parse cite command arguments
|
||||
* text.C (parse_text): handle natbib and jurabib citation commands
|
||||
|
||||
2004-07-29 Georg Baum <Georg.Baum@post.rwth-aachen.de>
|
||||
|
||||
* preamble.C (end_preamble): change file format from 228 to 235
|
||||
|
@ -39,6 +39,8 @@ using lyx::support::LibFileSearch;
|
||||
// special columntypes
|
||||
extern std::map<char, int> special_columns;
|
||||
|
||||
std::map<string, vector<string> > used_packages;
|
||||
|
||||
namespace {
|
||||
|
||||
const char * const known_languages[] = { "austrian", "babel", "bahasa",
|
||||
@ -103,8 +105,68 @@ void handle_opt(vector<string> & opts, char const * const * what, string & targe
|
||||
}
|
||||
|
||||
|
||||
void handle_package(string const & name, string const & options)
|
||||
/*!
|
||||
* Split a package options string (keyval format) into a vector.
|
||||
* Example input:
|
||||
* authorformat=smallcaps,
|
||||
* commabeforerest,
|
||||
* titleformat=colonsep,
|
||||
* bibformat={tabular,ibidem,numbered}
|
||||
*/
|
||||
vector<string> split_options(string const & input)
|
||||
{
|
||||
vector<string> options;
|
||||
string option;
|
||||
Parser p(input);
|
||||
while (p.good()) {
|
||||
Token const & t = p.get_token();
|
||||
if (t.asInput() == ",") {
|
||||
options.push_back(option);
|
||||
option.erase();
|
||||
} else if (t.asInput() == "=") {
|
||||
option += '=';
|
||||
p.skip_spaces(true);
|
||||
if (p.next_token().asInput() == "{")
|
||||
option += '{' + p.getArg('{', '}') + '}';
|
||||
} else if (t.cat() != catSpace)
|
||||
option += t.asInput();
|
||||
}
|
||||
|
||||
if (!option.empty())
|
||||
options.push_back(option);
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
* Add package \p name with options \p options to used_packages.
|
||||
* Remove options from \p options that we don't want to output.
|
||||
*/
|
||||
void add_package(string const & name, vector<string> & options)
|
||||
{
|
||||
// every package inherits the global options
|
||||
if (used_packages.find(name) == used_packages.end())
|
||||
used_packages[name] = split_options(h_options);
|
||||
|
||||
vector<string> & v = used_packages[name];
|
||||
v.insert(v.end(), options.begin(), options.end());
|
||||
if (name == "jurabib") {
|
||||
// Don't output the order argument (see the cite command
|
||||
// handling code in text.C).
|
||||
vector<string>::iterator end =
|
||||
remove(options.begin(), options.end(), "natbiborder");
|
||||
end = remove(options.begin(), end, "jurabiborder");
|
||||
options.erase(end, options.end());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void handle_package(string const & name, string const & opts)
|
||||
{
|
||||
vector<string> options = split_options(opts);
|
||||
add_package(name, options);
|
||||
|
||||
//cerr << "handle_package: '" << name << "'\n";
|
||||
if (name == "a4wide") {
|
||||
h_papersize = "a4paper";
|
||||
@ -121,21 +183,42 @@ void handle_package(string const & name, string const & options)
|
||||
; // ignore this
|
||||
else if (name == "fontenc")
|
||||
; // ignore this
|
||||
else if (name == "inputenc")
|
||||
h_inputencoding = options;
|
||||
else if (name == "makeidx")
|
||||
else if (name == "inputenc") {
|
||||
h_inputencoding = opts;
|
||||
options.clear();
|
||||
} else if (name == "makeidx")
|
||||
; // ignore this
|
||||
else if (name == "verbatim")
|
||||
; // ignore this
|
||||
else if (is_known(name, known_languages)) {
|
||||
h_language = name;
|
||||
h_quotes_language = name;
|
||||
} else {
|
||||
if (!options.empty())
|
||||
h_preamble << "\\usepackage[" << options << "]{" << name << "}\n";
|
||||
else
|
||||
h_preamble << "\\usepackage{" << name << "}\n";
|
||||
} else if (name == "natbib") {
|
||||
h_cite_engine = "natbib_authoryear";
|
||||
vector<string>::iterator it =
|
||||
find(options.begin(), options.end(), "authoryear");
|
||||
if (it != options.end())
|
||||
options.erase(it);
|
||||
else {
|
||||
it = find(options.begin(), options.end(), "numbers");
|
||||
if (it != options.end()) {
|
||||
h_cite_engine = "natbib_numerical";
|
||||
options.erase(it);
|
||||
}
|
||||
}
|
||||
} else if (name == "jurabib") {
|
||||
h_cite_engine = "jurabib";
|
||||
} else if (options.empty())
|
||||
h_preamble << "\\usepackage{" << name << "}\n";
|
||||
else {
|
||||
h_preamble << "\\usepackage[" << opts << "]{" << name << "}\n";
|
||||
options.clear();
|
||||
}
|
||||
|
||||
// We need to do something with the options...
|
||||
if (!options.empty())
|
||||
cerr << "Ignoring options '" << join(options, ",")
|
||||
<< "' of package " << name << '.' << endl;
|
||||
}
|
||||
|
||||
|
||||
@ -362,6 +445,17 @@ LyXTextClass const parse_preamble(Parser & p, ostream & os, string const & force
|
||||
h_preamble << "\\begin{" << name << "}";
|
||||
}
|
||||
|
||||
else if (t.cs() == "jurabibsetup") {
|
||||
vector<string> jurabibsetup =
|
||||
split_options(p.getArg('{', '}'));
|
||||
// add jurabibsetup to the jurabib package options
|
||||
add_package("jurabib", jurabibsetup);
|
||||
if (!jurabibsetup.empty()) {
|
||||
h_preamble << "\\jurabibsetup{"
|
||||
<< join(jurabibsetup, ",") << '}';
|
||||
}
|
||||
}
|
||||
|
||||
else if (!t.cs().empty())
|
||||
h_preamble << '\\' << t.cs();
|
||||
}
|
||||
|
@ -26,6 +26,9 @@ class Context;
|
||||
/// in preamble.C
|
||||
LyXTextClass const parse_preamble(Parser & p, std::ostream & os, std::string const & forceclass);
|
||||
|
||||
/// used packages with options
|
||||
extern std::map<std::string, std::vector<std::string> > used_packages;
|
||||
|
||||
|
||||
/// in text.C
|
||||
void parse_text(Parser & p, std::ostream & os, unsigned flags, bool outer,
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include "support/tostr.h"
|
||||
#include "support/filetools.h"
|
||||
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
@ -82,6 +84,29 @@ namespace {
|
||||
char const * const known_latex_commands[] = { "ref", "cite", "label", "index",
|
||||
"printindex", "pageref", "url", "vref", "vpageref", "prettyref", "eqref", 0 };
|
||||
|
||||
/*!
|
||||
* natbib commands.
|
||||
* We can't put these into known_latex_commands because the argument order
|
||||
* is reversed in lyx if there are 2 arguments.
|
||||
* The starred forms are also known.
|
||||
*/
|
||||
char const * const known_natbib_commands[] = { "cite", "citet", "citep",
|
||||
"citealt", "citealp", "citeauthor", "citeyear", "citeyearpar",
|
||||
"citefullauthor", "Citet", "Citep", "Citealt", "Citealp", "Citeauthor", 0 };
|
||||
|
||||
/*!
|
||||
* jurabib commands.
|
||||
* We can't put these into known_latex_commands because the argument order
|
||||
* is reversed in lyx if there are 2 arguments.
|
||||
* No starred form other than "cite*" known.
|
||||
*/
|
||||
char const * const known_jurabib_commands[] = { "cite", "citet", "citep",
|
||||
"citealt", "citealp", "citeauthor", "citeyear", "citeyearpar", "fullcite",
|
||||
// jurabib commands not (yet) supported by LyX:
|
||||
// "footcite", "footcitet", "footcitep", "footcitealt", "footcitealp",
|
||||
// "footciteauthor", "footciteyear", "footciteyearpar",
|
||||
"citefield", "citetitle", "cite*", 0 };
|
||||
|
||||
/// LaTeX names for quotes
|
||||
char const * const known_quotes[] = { "glqq", "grqq", "quotedblbase",
|
||||
"textquotedblleft", "quotesinglbase", "guilsinglleft", "guilsinglright", 0};
|
||||
@ -821,6 +846,35 @@ void parse_text_attributes(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
os << '\n' << attribute << ' ' << oldvalue << " \n";
|
||||
}
|
||||
|
||||
|
||||
/// get the arguments of a natbib or jurabib citation command
|
||||
std::pair<string, string> getCiteArguments(Parser & p, ostream & os,
|
||||
Context & context, bool natbibOrder)
|
||||
{
|
||||
// We need to distinguish "" and "[]", so we can't use p.getOpt().
|
||||
|
||||
// text before the citation
|
||||
string before;
|
||||
// text after the citation
|
||||
string after;
|
||||
|
||||
eat_whitespace(p, os, context, false);
|
||||
if (p.next_token().asInput() == "[") {
|
||||
after = '[' + p.getArg('[', ']') + ']';
|
||||
eat_whitespace(p, os, context, false);
|
||||
if (natbibOrder) {
|
||||
if (p.next_token().asInput() == "[") {
|
||||
before = after;
|
||||
after = '[' + p.getArg('[', ']') + ']';
|
||||
}
|
||||
} else {
|
||||
if (p.next_token().asInput() == "[")
|
||||
before = '[' + p.getArg('[', ']') + ']';
|
||||
}
|
||||
}
|
||||
return std::make_pair(before, after);
|
||||
}
|
||||
|
||||
} // anonymous namespace
|
||||
|
||||
|
||||
@ -830,6 +884,8 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
LyXLayout_ptr newlayout;
|
||||
// Store the latest bibliographystyle (needed for bibtex inset)
|
||||
string bibliographystyle;
|
||||
bool const use_natbib = used_packages.find("natbib") != used_packages.end();
|
||||
bool const use_jurabib = used_packages.find("jurabib") != used_packages.end();
|
||||
while (p.good()) {
|
||||
Token const & t = p.get_token();
|
||||
|
||||
@ -1402,7 +1458,98 @@ void parse_text(Parser & p, ostream & os, unsigned flags, bool outer,
|
||||
os << "\n\\" << t.cs() << " default \n";
|
||||
}
|
||||
|
||||
else if (use_natbib &&
|
||||
is_known(t.cs(), known_natbib_commands) &&
|
||||
((t.cs() != "citefullauthor" &&
|
||||
t.cs() != "citeyear" &&
|
||||
t.cs() != "citeyearpar") ||
|
||||
p.next_token().asInput() != "*")) {
|
||||
context.check_layout(os);
|
||||
// tex lyx
|
||||
// \citet[before][after]{a} \citet[after][before]{a}
|
||||
// \citet[before][]{a} \citet[][before]{a}
|
||||
// \citet[after]{a} \citet[after]{a}
|
||||
// \citet{a} \citet{a}
|
||||
string command = '\\' + t.cs();
|
||||
if (p.next_token().asInput() == "*") {
|
||||
command += '*';
|
||||
p.get_token();
|
||||
}
|
||||
if (command == "\\citefullauthor")
|
||||
// alternative name for "\\citeauthor*"
|
||||
command = "\\citeauthor*";
|
||||
|
||||
// text before the citation
|
||||
string before;
|
||||
// text after the citation
|
||||
string after;
|
||||
|
||||
boost::tie(before, after) =
|
||||
getCiteArguments(p, os, context, true);
|
||||
if (command == "\\cite") {
|
||||
// \cite without optional argument means
|
||||
// \citet, \cite with at least one optional
|
||||
// argument means \citep.
|
||||
if (before.empty() && after.empty())
|
||||
command = "\\citet";
|
||||
else
|
||||
command = "\\citep";
|
||||
}
|
||||
if (before.empty() && after == "[]")
|
||||
// avoid \citet[]{a}
|
||||
after.erase();
|
||||
else if (before == "[]" && after == "[]") {
|
||||
// avoid \citet[][]{a}
|
||||
before.erase();
|
||||
after.erase();
|
||||
}
|
||||
begin_inset(os, "LatexCommand ");
|
||||
os << command << after << before
|
||||
<< '{' << p.verbatim_item() << "}\n";
|
||||
end_inset(os);
|
||||
}
|
||||
|
||||
else if (use_jurabib &&
|
||||
is_known(t.cs(), known_jurabib_commands)) {
|
||||
context.check_layout(os);
|
||||
string const command = '\\' + t.cs();
|
||||
char argumentOrder = '\0';
|
||||
vector<string> const & options = used_packages["jurabib"];
|
||||
if (std::find(options.begin(), options.end(),
|
||||
"natbiborder") != options.end())
|
||||
argumentOrder = 'n';
|
||||
else if (std::find(options.begin(), options.end(),
|
||||
"jurabiborder") != options.end())
|
||||
argumentOrder = 'j';
|
||||
|
||||
// text before the citation
|
||||
string before;
|
||||
// text after the citation
|
||||
string after;
|
||||
|
||||
boost::tie(before, after) =
|
||||
getCiteArguments(p, os, context,
|
||||
argumentOrder != 'j');
|
||||
string const citation = p.verbatim_item();
|
||||
if (!before.empty() && argumentOrder == '\0') {
|
||||
cerr << "Warning: Assuming argument order "
|
||||
<< "of jurabib version 0.6 for\n'"
|
||||
<< command << before << after << '{'
|
||||
<< citation << "}'.\n"
|
||||
<< "Add 'jurabiborder' to the jurabib "
|
||||
<< "package options if you used an\n"
|
||||
<< "earlier jurabib version." << endl;
|
||||
}
|
||||
begin_inset(os, "LatexCommand ");
|
||||
os << command << after << before
|
||||
<< '{' << citation << "}\n";
|
||||
end_inset(os);
|
||||
}
|
||||
|
||||
else if (is_known(t.cs(), known_latex_commands)) {
|
||||
// This needs to be after the check for natbib and
|
||||
// jurabib commands, because "cite" has different
|
||||
// arguments with natbib and jurabib.
|
||||
context.check_layout(os);
|
||||
begin_inset(os, "LatexCommand ");
|
||||
os << '\\' << t.cs();
|
||||
|
Loading…
Reference in New Issue
Block a user