mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-09 18:31:04 +00:00
Support for multiple bibliographies setting "per child"
This adds support for the chapterbib package, but also adds ways to produce this sort of multibib with biblatex and bibtopic (which are both incompatible with chapterbib). File format change.
This commit is contained in:
parent
401961d087
commit
bedebfc45a
@ -7,9 +7,16 @@ changes happened in particular if possible. A good example would be
|
||||
|
||||
-----------------------
|
||||
|
||||
2017-02-04 Jürgen Spitzmüller <spitz@lyx.org>
|
||||
* Format incremented to 534: Support for chapterbib
|
||||
- New buffer param value \multibib child
|
||||
LaTeX support either via biblatex's \newrefsection at the beginning
|
||||
of child documents, chapterbib or bibtopic's btUnit environment
|
||||
embracing the child content (if subdivided bibliography is requested).
|
||||
|
||||
2017-02-04 Jürgen Spitzmüller <spitz@lyx.org>
|
||||
* Format incremented to 533: Support for multiple bibliographies
|
||||
- New buffer param \multibib {none|part|chapter|section|subsetion}
|
||||
- New buffer param \multibib {none|part|chapter|section|subsection}
|
||||
LaTeX support either via biblatex option "refsection" or bibtopic's
|
||||
btUnit environment.
|
||||
- New btprint value "bibbysection" of CommandInset bibtex:
|
||||
|
@ -294,6 +294,7 @@
|
||||
\TestPackage{CJKutf8}
|
||||
\TestPackage{calc}
|
||||
\TestPackage{cancel}
|
||||
\TestPackage{chapterbib}
|
||||
\TestPackage{chemgreek}
|
||||
\TestPackage{chicago}
|
||||
\TestPackage{color} % this one should be there if graphics.sty is there.
|
||||
|
@ -1,5 +1,5 @@
|
||||
#LyX 2.3 created this file. For more info see http://www.lyx.org/
|
||||
\lyxformat 528
|
||||
\lyxformat 534
|
||||
\begin_document
|
||||
\begin_header
|
||||
\save_transient_properties true
|
||||
@ -5609,6 +5609,35 @@ bibtopic
|
||||
created bibliographies into sections.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsection
|
||||
chapterbib
|
||||
\end_layout
|
||||
|
||||
\begin_layout Description
|
||||
Found:
|
||||
\begin_inset Info
|
||||
type "package"
|
||||
arg "chapterbib"
|
||||
\end_inset
|
||||
|
||||
|
||||
\end_layout
|
||||
|
||||
\begin_layout Description
|
||||
CTAN:
|
||||
\family typewriter
|
||||
macros/latex/contrib/chapterbib/
|
||||
\end_layout
|
||||
|
||||
\begin_layout Description
|
||||
Notes: The package
|
||||
\family sans
|
||||
chapterbib
|
||||
\family default
|
||||
is used to generate multiple bibliographies per child with Bib\SpecialChar TeX
|
||||
.
|
||||
\end_layout
|
||||
|
||||
\begin_layout Subsection
|
||||
chicago
|
||||
\end_layout
|
||||
@ -6049,6 +6078,7 @@ lettrine
|
||||
LatexCommand href
|
||||
name "initials"
|
||||
target "http://en.wikipedia.org/wiki/Initial"
|
||||
literal "false"
|
||||
|
||||
\end_inset
|
||||
|
||||
|
@ -1735,6 +1735,111 @@ def revert_multibib(document):
|
||||
"end{btUnit}"
|
||||
"\\end_layout", "", "\\end_inset", "", "",
|
||||
"\\end_layout", ""]
|
||||
|
||||
|
||||
def revert_chapterbib(document):
|
||||
" Revert chapterbib support "
|
||||
|
||||
# 1. Get cite engine
|
||||
engine = "basic"
|
||||
i = find_token(document.header, "\\cite_engine", 0)
|
||||
if i == -1:
|
||||
document.warning("Malformed document! Missing \\cite_engine")
|
||||
else:
|
||||
engine = get_value(document.header, "\\cite_engine", i)
|
||||
|
||||
# 2. Do we use biblatex?
|
||||
biblatex = False
|
||||
if engine in ["biblatex", "biblatex-natbib"]:
|
||||
biblatex = True
|
||||
|
||||
# 3. Store multibib document header value
|
||||
multibib = ""
|
||||
i = find_token(document.header, "\\multibib", 0)
|
||||
if i != -1:
|
||||
multibib = get_value(document.header, "\\multibib", i)
|
||||
|
||||
if not multibib or multibib != "child":
|
||||
# nothing to do
|
||||
return
|
||||
|
||||
# 4. remove multibib header
|
||||
del document.header[i]
|
||||
|
||||
# 5. Biblatex
|
||||
if biblatex:
|
||||
# find include insets
|
||||
i = 0
|
||||
while (True):
|
||||
i = find_token(document.body, "\\begin_inset CommandInset include", i)
|
||||
if i == -1:
|
||||
break
|
||||
j = find_end_of_inset(document.body, i)
|
||||
if j == -1:
|
||||
document.warning("Can't find end of bibtex inset at line %d!!" %(i))
|
||||
i += 1
|
||||
continue
|
||||
parent = get_containing_layout(document.body, i)
|
||||
parbeg = parent[1]
|
||||
|
||||
# Insert ERT \\newrefsection before inset
|
||||
beg = ["\\begin_layout Standard",
|
||||
"\\begin_inset ERT", "status open", "",
|
||||
"\\begin_layout Plain Layout", "", "",
|
||||
"\\backslash",
|
||||
"newrefsection"
|
||||
"\\end_layout", "", "\\end_inset", "", "",
|
||||
"\\end_layout", ""]
|
||||
document.body[parbeg-1:parbeg-1] = beg
|
||||
j += len(beg)
|
||||
i = j + 1
|
||||
return
|
||||
|
||||
# 6. Bibtex/Bibtopic
|
||||
i = find_token(document.header, "\\use_bibtopic", 0)
|
||||
if i == -1:
|
||||
# this should not happen
|
||||
document.warning("Malformed LyX document! No \\use_bibtopic header found!")
|
||||
return
|
||||
if get_value(document.header, "\\use_bibtopic", i) == "true":
|
||||
# find include insets
|
||||
i = 0
|
||||
while (True):
|
||||
i = find_token(document.body, "\\begin_inset CommandInset include", i)
|
||||
if i == -1:
|
||||
break
|
||||
j = find_end_of_inset(document.body, i)
|
||||
if j == -1:
|
||||
document.warning("Can't find end of bibtex inset at line %d!!" %(i))
|
||||
i += 1
|
||||
continue
|
||||
parent = get_containing_layout(document.body, i)
|
||||
parbeg = parent[1]
|
||||
parend = parent[2]
|
||||
|
||||
# Insert wrap inset into \\begin{btUnit}...\\end{btUnit}
|
||||
beg = ["\\begin_layout Standard",
|
||||
"\\begin_inset ERT", "status open", "",
|
||||
"\\begin_layout Plain Layout", "", "",
|
||||
"\\backslash",
|
||||
"begin{btUnit}"
|
||||
"\\end_layout", "", "\\end_inset", "", "",
|
||||
"\\end_layout", ""]
|
||||
end = ["\\begin_layout Standard",
|
||||
"\\begin_inset ERT", "status open", "",
|
||||
"\\begin_layout Plain Layout", "", "",
|
||||
"\\backslash",
|
||||
"end{btUnit}"
|
||||
"\\end_layout", "", "\\end_inset", "", "",
|
||||
"\\end_layout", ""]
|
||||
document.body[parend+1:parend+1] = end
|
||||
document.body[parbeg-1:parbeg-1] = beg
|
||||
j += len(beg) + len(end)
|
||||
i = j + 1
|
||||
return
|
||||
|
||||
# 7. Chapterbib proper
|
||||
add_to_preamble(document, ["\\usepackage{chapterbib}"])
|
||||
|
||||
|
||||
##
|
||||
@ -1768,9 +1873,11 @@ convert = [
|
||||
[531, []],
|
||||
[532, [convert_literalparam]],
|
||||
[533, []],
|
||||
[534, []]
|
||||
]
|
||||
|
||||
revert = [
|
||||
[533, [revert_chapterbib]],
|
||||
[532, [revert_multibib]],
|
||||
[531, [revert_literalparam]],
|
||||
[530, [revert_qualicites]],
|
||||
|
@ -523,6 +523,14 @@ map<string, string> const & BufferParams::auto_packages()
|
||||
}
|
||||
|
||||
|
||||
bool BufferParams::useBibtopic() const
|
||||
{
|
||||
if (useBiblatex())
|
||||
return false;
|
||||
return (use_bibtopic || (!multibib.empty() && multibib != "child"));
|
||||
}
|
||||
|
||||
|
||||
AuthorList & BufferParams::authors()
|
||||
{
|
||||
return pimpl_->authorlist;
|
||||
@ -2218,7 +2226,7 @@ bool BufferParams::writeLaTeX(otexstream & os, LaTeXFeatures & features,
|
||||
delim = ",";
|
||||
}
|
||||
}
|
||||
if (!multibib.empty()) {
|
||||
if (!multibib.empty() && multibib != "child") {
|
||||
opts += delim + "refsection=" + multibib;
|
||||
delim = ",";
|
||||
}
|
||||
|
@ -379,7 +379,7 @@ public:
|
||||
/// All packages that can be switched on or off
|
||||
static std::map<std::string, std::string> const & auto_packages();
|
||||
/// Do we use the bibtopic package?
|
||||
bool useBibtopic() const { return (use_bibtopic || !multibib.empty()) && !useBiblatex(); }
|
||||
bool useBibtopic() const;
|
||||
/// Split bibliography?
|
||||
bool splitbib() const { return use_bibtopic; }
|
||||
/// Set split bibliography
|
||||
|
@ -402,6 +402,9 @@ bool Converters::convert(Buffer const * buffer,
|
||||
runparams.index_command = (buffer->params().index_command == "default") ?
|
||||
string() : buffer->params().index_command;
|
||||
runparams.document_language = buffer->params().language->babel();
|
||||
runparams.only_childbibs = !buffer->params().useBiblatex()
|
||||
&& !buffer->params().useBibtopic()
|
||||
&& buffer->params().multibib == "child";
|
||||
}
|
||||
|
||||
// Some converters (e.g. lilypond) can only output files to the
|
||||
|
@ -237,7 +237,7 @@ int LaTeX::run(TeXErrors & terr)
|
||||
/// in which case we will not need to run bibtex again.
|
||||
vector<AuxInfo> bibtex_info_old;
|
||||
if (!run_bibtex)
|
||||
bibtex_info_old = scanAuxFiles(aux_file);
|
||||
bibtex_info_old = scanAuxFiles(aux_file, runparams.only_childbibs);
|
||||
|
||||
++count;
|
||||
LYXERR(Debug::LATEX, "Run #" << count);
|
||||
@ -253,7 +253,7 @@ int LaTeX::run(TeXErrors & terr)
|
||||
scanres = scanLogFile(terr);
|
||||
}
|
||||
|
||||
vector<AuxInfo> const bibtex_info = scanAuxFiles(aux_file);
|
||||
vector<AuxInfo> const bibtex_info = scanAuxFiles(aux_file, runparams.only_childbibs);
|
||||
if (!run_bibtex && bibtex_info_old != bibtex_info)
|
||||
run_bibtex = true;
|
||||
|
||||
@ -491,12 +491,26 @@ bool LaTeX::runMakeIndexNomencl(FileName const & file,
|
||||
|
||||
|
||||
vector<AuxInfo> const
|
||||
LaTeX::scanAuxFiles(FileName const & file)
|
||||
LaTeX::scanAuxFiles(FileName const & file, bool const only_childbibs)
|
||||
{
|
||||
vector<AuxInfo> result;
|
||||
|
||||
// With chapterbib, we have to bibtex all children's aux files
|
||||
// but _not_ the master's!
|
||||
if (only_childbibs) {
|
||||
for (string const &s: children) {
|
||||
FileName fn =
|
||||
makeAbsPath(s, file.onlyPath().realPath());
|
||||
fn.changeExtension("aux");
|
||||
if (fn.exists())
|
||||
result.push_back(scanAuxFile(fn));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
result.push_back(scanAuxFile(file));
|
||||
|
||||
// This is for bibtopic
|
||||
string const basename = removeExtension(file.absFileName());
|
||||
for (int i = 1; i < 1000; ++i) {
|
||||
FileName const file2(basename
|
||||
@ -647,6 +661,7 @@ int LaTeX::scanLogFile(TeXErrors & terr)
|
||||
string child_name;
|
||||
int pnest = 0;
|
||||
stack <pair<string, int> > child;
|
||||
children.clear();
|
||||
|
||||
string token;
|
||||
while (getline(ifs, token)) {
|
||||
@ -675,6 +690,7 @@ int LaTeX::scanLogFile(TeXErrors & terr)
|
||||
if (regex_match(substr, sub, child_file)) {
|
||||
string const name = sub.str(1);
|
||||
child.push(make_pair(name, pnest));
|
||||
children.push_back(name);
|
||||
i += len;
|
||||
}
|
||||
} else if (token[i] == ')') {
|
||||
|
@ -197,7 +197,8 @@ private:
|
||||
std::string const &, std::string const &);
|
||||
|
||||
///
|
||||
std::vector<AuxInfo> const scanAuxFiles(support::FileName const &);
|
||||
std::vector<AuxInfo> const scanAuxFiles(support::FileName const &,
|
||||
bool const only_childbibs = false);
|
||||
|
||||
///
|
||||
AuxInfo const scanAuxFile(support::FileName const &);
|
||||
@ -242,6 +243,9 @@ private:
|
||||
|
||||
/// Do we use biber?
|
||||
bool biber;
|
||||
|
||||
///
|
||||
std::vector <std::string> children;
|
||||
};
|
||||
|
||||
|
||||
|
@ -963,6 +963,7 @@ char const * bibliofeatures[] = {
|
||||
"authordate1-4",
|
||||
"babelbib",
|
||||
"bibgerm",
|
||||
"chapterbib",
|
||||
"chicago",
|
||||
"chscite",
|
||||
"harvard",
|
||||
|
@ -24,7 +24,8 @@ OutputParams::OutputParams(Encoding const * enc)
|
||||
encoding(enc), free_spacing(false), use_babel(false), use_polyglossia(false),
|
||||
use_indices(false), use_japanese(false), linelen(0), depth(0),
|
||||
exportdata(new ExportData), inDisplayMath(false), wasDisplayMath(false),
|
||||
inComment(false), openbtUnit(false), inTableCell(NO), inFloat(NONFLOAT),
|
||||
inComment(false), openbtUnit(false), only_childbibs(false),
|
||||
inTableCell(NO), inFloat(NONFLOAT),
|
||||
inIndexEntry(false), inIPA(false), inDeletedInset(0),
|
||||
changeOfDeletedInset(Change::UNCHANGED),
|
||||
par_begin(0), par_end(0), lastid(-1), lastpos(0), isLastPar(false),
|
||||
|
@ -209,6 +209,11 @@ public:
|
||||
*/
|
||||
bool openbtUnit;
|
||||
|
||||
/** Process only the children's aux files with BibTeX.
|
||||
* This is necessary with chapterbib.
|
||||
*/
|
||||
bool only_childbibs;
|
||||
|
||||
/** Whether we are in a table cell.
|
||||
* For newline, it matters whether its content is aligned or not.
|
||||
*/
|
||||
|
@ -3169,6 +3169,7 @@ void GuiDocument::paramsToDialog()
|
||||
biblioModule->bibunitsCO->addItem(qt_("per section"), toqstr("section"));
|
||||
if (documentClass().hasLaTeXLayout("subsection"))
|
||||
biblioModule->bibunitsCO->addItem(qt_("per subsection"), toqstr("subsection"));
|
||||
biblioModule->bibunitsCO->addItem(qt_("per child document"), toqstr("child"));
|
||||
|
||||
int const mbpos = biblioModule->bibunitsCO->findData(toqstr(bp_.multibib));
|
||||
if (mbpos != -1)
|
||||
|
@ -222,6 +222,12 @@ docstring InsetBibtex::toolTip(BufferView const & /*bv*/, int /*x*/, int /*y*/)
|
||||
tip += ", ";
|
||||
tip += _("included in TOC");
|
||||
}
|
||||
if (!buffer().parent()
|
||||
&& buffer().params().multibib == "child") {
|
||||
tip += "<br />";
|
||||
tip += _("Note: This bibliography is not output, since bibliographies in the master file "
|
||||
"are not allowed with the setting 'Multiple bibliographies per child document'");
|
||||
}
|
||||
} else {
|
||||
tip += _("Lists:") + " ";
|
||||
if (btprint == "bibbysection")
|
||||
@ -262,6 +268,11 @@ void InsetBibtex::latex(otexstream & os, OutputParams const & runparams) const
|
||||
// or
|
||||
// \bibbysection[biblatexopts] - if btprint is "bibbysection"
|
||||
|
||||
// chapterbib does not allow bibliographies in the master
|
||||
if (!usingBiblatex() && !runparams.is_child
|
||||
&& buffer().params().multibib == "child")
|
||||
return;
|
||||
|
||||
string style = to_utf8(getParam("options")); // maybe empty! and with bibtotoc
|
||||
string bibtotoc;
|
||||
if (prefixIs(style, "bibtotoc")) {
|
||||
@ -876,8 +887,11 @@ bool InsetBibtex::delDatabase(docstring const & db)
|
||||
|
||||
void InsetBibtex::validate(LaTeXFeatures & features) const
|
||||
{
|
||||
if (features.buffer().masterParams().useBibtopic())
|
||||
BufferParams const & mparams = features.buffer().masterParams();
|
||||
if (mparams.useBibtopic())
|
||||
features.require("bibtopic");
|
||||
else if (!mparams.useBiblatex() && mparams.multibib == "child")
|
||||
features.require("chapterbib");
|
||||
// FIXME XHTML
|
||||
// It'd be better to be able to get this from an InsetLayout, but at present
|
||||
// InsetLayouts do not seem really to work for things that aren't InsetTexts.
|
||||
|
@ -1267,9 +1267,19 @@ void latexParagraphs(Buffer const & buf,
|
||||
{ os << "% LaTeX Output Error\n"; return; } );
|
||||
|
||||
BufferParams const & bparams = buf.params();
|
||||
BufferParams const & mparams = buf.masterParams();
|
||||
|
||||
bool const maintext = text.isMainText();
|
||||
bool const is_child = buf.masterBuffer() != &buf;
|
||||
bool const multibib_child = maintext && is_child
|
||||
&& mparams.multibib == "child";
|
||||
|
||||
if (multibib_child && mparams.useBiblatex())
|
||||
os << "\\newrefsection";
|
||||
else if (multibib_child && mparams.useBibtopic()) {
|
||||
os << "\\begin{btUnit}\n";
|
||||
runparams.openbtUnit = true;
|
||||
}
|
||||
|
||||
// Open a CJK environment at the beginning of the main buffer
|
||||
// if the document's language is a CJK language
|
||||
@ -1443,6 +1453,11 @@ void latexParagraphs(Buffer const & buf,
|
||||
if (state->cjk_inherited_ == 0)
|
||||
state->open_encoding_ = CJK;
|
||||
}
|
||||
|
||||
if (multibib_child && mparams.useBibtopic()) {
|
||||
os << "\\end{btUnit}\n";
|
||||
runparams.openbtUnit = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -154,6 +154,8 @@ Format LaTeX feature LyX feature
|
||||
\bibbysection[<opts>] \begin_inset CommandInset bibtex
|
||||
biblatexopts "<opts>"
|
||||
btprint "bibbysection"
|
||||
534 Chapterbib support
|
||||
\usepackage{chapterbib} \multibib child
|
||||
|
||||
|
||||
|
||||
|
@ -32,8 +32,8 @@ extern char const * const lyx_version_info;
|
||||
|
||||
// Do not remove the comment below, so we get merge conflict in
|
||||
// independent branches. Instead add your own.
|
||||
#define LYX_FORMAT_LYX 533 // spitz: multibib
|
||||
#define LYX_FORMAT_TEX2LYX 533
|
||||
#define LYX_FORMAT_LYX 534 // spitz: chapterbib support
|
||||
#define LYX_FORMAT_TEX2LYX 534
|
||||
|
||||
#if LYX_FORMAT_TEX2LYX != LYX_FORMAT_LYX
|
||||
#ifndef _MSC_VER
|
||||
|
Loading…
Reference in New Issue
Block a user